Verification: a143cc29221c9be0

Namespace for functions in php

Namespace for functions in php

Explanations

Explanation 1

Assume that we have a variable named $title in the global scope of a PHP script. Inside a function, we have another variable with the same name $title, and we assign and change values of it within the function. But, the global variable remains unchanged. This is variable scope. In the same way, classes can be namespaced to give it scope.

Explanation 2

Assume that you are creating an open-source PHP library to send emails and you share that with the developer community. Your library has a class named Email. Then, a developer downloads your library. But, if he already had a class called Email, Name Collision occurs. You will need to rename those classes or use a smarter solution: Namespaces.

Explanation 3 - The Simplest

Two people can be named "Jack". We can separate them by their surname. In the same way, two classes can have the same name. We can separate them by namespacing.

What can namespaces do?

  • Namespaces can prevent name collision
  • Namespaces can make our code more organized

Why Namespaces in PHP?

In PHP, you cannot have two classes with the same name. If you need two classes to handle your blog users and app users, you will need to name those: Blog_User and App_User. But, those prefixes are hard to manage.

Namespaces can be used to simplify the process and make it more organized. Namespaces give you more control.

Namespaces and File Structure

The concept of defining and calling namespaces is similar to the normal file structure in our operating systems.

Think namespaces as folders and files as classes.

  • The /lib/math folder can have multiple files in it, numbers.php, calculus.php and so on. But, no multiple files with the same name.
  • To access numbers.php from the calculus.php file, you can directly refer to numbers.php
  • The /lib/physics folder can also have multiple files, mechanics.php, electromagnetism.php and more. Also, you can have numbers.php in /lib/physics even it exists in the /lib/math folder.
  • Inside the physics folder, if you use numbers.php directly it will refer to /lib/physics/numbers.php
  • Inside the physics folder, if you needed to refer the numbers.php which exists in the /lib/math folder, you will need to use /lib/math/numbers.php

Namespaces work in the same way.

Global Namespace

When you declare a class (or function or constant) without a namespace it can be called "an item in the global namespace".

How to Define Namespaces?

The namespace keyword followed by the namespace name is used to declare a namespace in PHP.

Namespace name should be a valid PHP identifier. Namespace declaration should be the first thing in a PHP file. (with exception of declare keyword).

Declaring PHP Namespaces

Declaring PHP Namespaces

Any valid PHP code can be in a namespace, but only classes, interfaces, constants, and functions are affected. Even it is possible to have multiple namespaces in the same file, it is not recommended.

Creating and Accessing Namespaced Classes

One special thing to remember throughout this tutorial: PHP is always relative to the current namespace.

If we add the namespace declaration at the top of a PHP file, all the classes, functions and constants will be items of that namespace.

Items of Namespaces

Items of Namespaces

Let's create a file named Math.php and add the following code.

Math.php


  • First, we declare the namespace. (So, all the classes, interfaces, constants and function below it will be items of that namespace)
  • Then, we declared a normal function.
  • Then, a class constant.
  • Then, a class.

Here comes the interesting part. Let's create another file called usage.php and access the above Math namespace's items (functions, constants, and classes).

usage.php


The \ character is used to go a level down in namespaces.

Sub-Namespaces

In an operating system, folders can contain folders. In the same way, namespaces can contain namespaces. They are called sub-namespaces.


Hereafter, we will only be using classes in namespaces. (No more functions and constants as this is the OOP section in this tutorial)

Recommended Structure for Namespaces

We will learn all the recommendations for Object-Oriented programming in PHP in a later chapter. But, here we will learn how to structure your namespaces as it is really important to know.

It is recommended to map namespaces with local directories of your computer. See this example:

  • Assume you have your project in the /var/www folder.
  • To make it clean, we will have our PHP class files in /var/www/src folder.
  • Each namespace will have a directory named as the same name as the namespace. (Match the letter case)
  • So, the folder representing Math namespace will be /var/www/src/Math.
  • Each class should be in a single PHP file (with .php) and one PHP class file should only contain one class definition.
    Ex: Math\Addition => /var/www/src/Math/Addition.php
  • Sub-Namespaces should have their own folders to contain classes. For example, the classes of Math\Geometry sub-namespace should be in the folder /var/www/src/Math/Geometry

These are recommendations. Not rules. You can follow them if you like.

Example - Math Namespace

Let's understand more by doing. In this example, we will be creating a namespace named Math and add sub-namespaces, classes into it. Here's the structure.

  • Main namespace: Math
  • One Subnamespaces: Math\Geometry (To handle geometry)
  • Two Classes: Math\Constants (To save frequently used constants) and Math\Geometry\Circle (To handle circle)

Here's the final structure of our project.


/src
	/Math
		/Geometry
			Circle.php
		Constants.php

Math/Constants.php


Math/Geometry/Circle.php


 radius = $radius;
	}
	public function getDiameter() {
		return $this -> radius * 2;
	}
	public function getArea() {
		// (pi)(r^2)
		return \Math\Constants::PI * $this -> radius ** 2; 
	}
	public function getCircumference() {
		// 2(pi)(r)
		return 2 * \Math\Constants::PI * $this -> radius;
	}
}

In Circle.php, we used \Math\Constants::PI to refer the constant in Constants.php file. This is because PHP is always relative to the current namespace. When a namespace starts with a backslash (\), the name will be resolved relative to the global namespace.

  • If we used Constants::PI in Circle.php, it would refer \Math\Geometry\Constants::PI.
  • If we used Math\Constants::PI (without starting backslash) in Circle.php, it it will refer to \Math\Geometry\Math\Constants::PI

Simply, class names are relative to the current namespace. Starting backslash (\) is used to go back to the start. Relative namespaces aren't currently supported in PHP. (../Constants::PI is not supported)

Finally, let's use our classes in index.php (which should be in the root folder of your project)


 getDiameter(); 		// 20
echo $circle -> getArea(); 			// 314.159
echo $circle -> getCircumference(); // 62.8318

  • First, We included the class files.
  • Then, used the Math\Geometry\Circle class and its methods.

Important to note that index.php is in the global namespaces as it is not in any namespace.

Using "use" in Namespaces to Import

The use keyword can be used to import a class to the current scope.

If you add the following code in your index.php, Math\Geometry\Circle class will be imported to the current scope.


You can import both namespaces and classes


You can nickname (or alias) the imports

There are two places to use nicknames (or aliases) for importing classes.

  • When you already have a class named the same name as the importing class
  • When you need a more convenient (or easy) name for the importing class

The as keyword is used for nicknaming.


Changing the previous example

Let's change our index.php of the previous example adding use statements to import the class.


As we did not have an as keyword, the imported class could be referred to using Circle. We can also import the Circle class with a nickname.


Wait! It is not a good practice to use names like C. Always use descriptive names.

Here's a task for you: Use use as in the Circle.php and replace the \Math\Constants::PI with a short name.

Organizing Code with Namespaces

One of the main uses of namespaces is for organizing codes. Let's assume that you are creating an open-source library.

  • You will need to prevent name collision. So, it's better to add all the classes into a namespace. (Named as your name or library's name).
  • Group similar classes into a subnamespace.
  • Use the folder structure which we learned early correctly.

Creating a namespace

To create a namespace in PHP, use the namespace keyword followed by the namespace name. The namespace declaration must be the very first line after opening tag:

Note: The file containing namespaced code must declare the namespace at the top of the file before any other code or HTML.

Once the namespace declared at the top of a PHP file, all code within that file belongs to that namespace. In above example, the aFunciton and bFunction functions belongs to the brainbell.

It is also possible to have two or more namespaces in a file by wrapping the code for the namespace in braces:

Note: This usage is not standard practice. Although you can declare multiple namespaces within a single PHP file, this is not good coding practice.

Global namespace

A file that not declared namespace keyword at the top; belongs to the global namespace. For example:

//Global namespace

namespace example

Once you’ve declared a namespace at the top of a PHP file, all code within that file belongs to that namespace. To use a class, function or constant that was declared in the same namespace, just write its name as normal, for example: $var = aFunction();:

//a.php

 function aFunction() {
  return true;
 }
 
 $var = aFunction(); //true

To use a namespaced class, function or constant from outside a namespace, write the namespace name, followed by a backslash \, followed by the class, function or constant name, for example:

 //b.php

 require ( 'a.php' );

 $var = brainbell\aFunction(); //true

Let’s create the same function name aFunction inside the b.php :

 //b.php

 require ( 'a.php' );

 function aFunction() {
  return 'hello world';
 } 
 
 $var1 = aFunction(); // hello world
 $var  = brainbell\aFunction(); // true

The above example will generate the following error if you remove the namespace brainbell; from the top of a.php file:

Fatal error: Cannot redeclare aFunction() (previously declared in b.php:8) in a.php on line 7

Thanks to PHP namespace, the names of both aFunction() functions no longer clash.

Sub-namespaces

You can also create sub-namespaces, much like sub-folders (or sub-directories) in a file system. This allows you to create a namespace hierarchy. You separate each namespace level with a backslash \ character:

The above code declares the template namespace inside the brainbell namespace. Let’s declare the same name function aFunction inside the sub-namespaced file and save it as c.php.

Next, edit the b.php (which we’ve already created in previous example) and include the c.php file. Now you can see that all files a.php, b.php and c.php declared the aFunction() function but they not clashing with each other nor generating any error because they are all in different namespaces:

 require ( 'c.php' ); // brainbell\template
 
 function aFunction() {
  return 'hello world';
 }

 $var  = aFunction(); // hello world
 $var1 = brainbell\aFunction(); // true
 $var2 = brainbell\template\aFunction(); //100

 //Print information
 echo '
';
 var_dump($var);
 var_dump($var1);
 var_dump($var2);

Let’s create another file d.php and write the following code to call brainbell\template\aFunction() from code that is within the brainbell namespace:

$var = template\aFunction(); //100
var_dump($var);

You can specify namespaces using relative notation, much like working with relative paths.

Namespace aliases

If you’re working with a big namespace hierarchy, specifying the full namespace name each time can get tiresome:

To get around this problem, you can use a namespace alias , which works much like a symbolic link in UNIX file systems. To create an alias you write:

use namespace as alias;

Once you’ve created an alias, you can use it in place of the full namespace name:

You can leave out the as statement (and the name that follows), in which case the use statement uses the last portion of the namespace name as the alias. So the following two lines of code are equivalent:

use brainbell\template\db\views as views;
use brainbell\template\db\views;