📜 ⬆️ ⬇️

PHP Namespaces

On Habré you can find a lot of articles about namespaces in PHP, but this one helped me, and I want to share it with her. Surely there are those to whom this translation will help.

The path to PHP namespace support was thorny. But fortunately, it was added to the language in PHP 5.3, and the structure of the PHP code has greatly improved since then. But how exactly do we use them?

What are namespaces?


“Don't forget the backslash when you store the name of the namespace as a string!”

Imagine a namespace like a box in which you can put anything: a pencil, a ruler, a piece of paper, and so on. These are your things. Right under your box, there is someone else's box, and its owner keeps the same things in it. To avoid using each other's items, you decided to label the boxes so that it became clear to whom it belongs.

Previously, developers had to use prefixes with underscores in their classes, functions, and constants to separate code. This is equivalent to the fact that everyone will label their belongings and they will be stored in one large box. Of course, this is at least at least some kind of organization, but it is very inefficient.

Namespaces will help! You can declare the same function, class, interface, and define a constant in separate namespaces without getting fatal errors. At its core, a namespace is nothing more than hierarchically labeled code blocks containing plain PHP code.
')

You use them!


It is important to understand that you are indirectly using namespaces; Since PHP 5.3, all definitions that are not yet declared in user-defined namespaces fall under the global namespace.

The global namespace also stores all internal PHP definitions, such as mysqli_connect() , and the Exception class. Since the global namespace does not have a unique identifying name, it is most often called a global space .
Please note that the use of the namespace is optional.
Your PHP script will work fine without them, and this behavior will not change very soon.

Namespace Definition


The file containing the namespace must contain its declaration at the beginning before any other code. The only thing that can be declared before the namespace is the reserved word declare , the expression declare may appear before the namespace declaration to indicate the encoding of the file.

Namespaces are declared using the namespace reserved word. Namespaces follow the same rules as other identifiers in PHP. Thus, the namespace must begin with a letter or underscore followed by any number of letters, numbers, or underscores .

 <?php namespace MyProject { //  PHP   , -  function run() { echo 'Running from a namespace!'; } } 

If you want to define a block of code in global space, you can use the namespace keyword without adding a name.

 <?php namespace { //  ! } 

You can use multiple namespaces in one file.

 <?php namespace MyProject { } namespace MySecondProject { } namespace { } 

You can also use the same namespace for several different files; The file connection process will automatically merge them. It is a good coding practice to limit the number of namespace definitions to a single file, just as you could do with classes.
The namespace is used to avoid conflicting definitions and introduce more flexibility and organization into the program code.

Note that curly braces are completely optional. In fact, using the rule of one namespace in one file and omitting curly brackets you make your code much cleaner - there is no need to indent (tab) for nested code.

Subspaces of names


Namespaces can follow a specific hierarchy, just like the directories in the file system on a computer. Subspaces of names are extremely useful for organizing the structure of a project. For example, if your project requires access to the database, you can put the code for the database exception handler and connection handler in the Database namespace.

For flexibility, it is wise to store nested namespaces in subdirectories. This contributes to the structuring of the project and makes it much easier to use its autoloaders, which follow the PSR-4 standard .

PHP uses a backslash as the namespace separator.

image

An interesting fact: in the RFC , to decide which namespace delimiter should be used, the option of using an emoticon was considered.

 // myproject/database/connection.php <?php namespace MyProject\Database class Connection { //      } 

You can use as many nested namespaces as you like.

 <?php namespace MyProject\Blog\Auth\Handler\Social; class Twitter { //    Twitter } 

Defining a namespace with nested code blocks is not supported. The following example will return a fatal error: "Namespace declarations cannot be nested (Namespace declarations can not be nested)."

 <?php namespace MyProject { namespace Database { class Connection { } } } 

Calling code from the namespace


If you want to create a new instance of an object, call a function, or use constants from different namespaces, you use a backslash. There are three types of namespace name definitions:




Incomplete name


This is the name of a class, function, or constant that does not include a reference to any namespace. For those who are just starting to work with the namespace, this is the usual point of view.

 <?php namespace MyProject; class MyClass { static function static_method() { echo 'Hello, world!'; } } //  ,      (MyProject\MyClass) MyClass:static_method(); 

Full name


So we get access to the namespace hierarchy; separated by a forward slash.

 <?php namespace MyProject; require 'myproject/database/connection.php'; //  ,      MyProject $connection = new Database\Connection(); 

The example below will return a fatal error: "Fatal error: Class 'MyProject \ Database \ MyProject \ FileAccess \ Input' not found", because MyProject\FileAccess\Input not related to the namespace you are in.

 <?php namespace MyProject\Database; require 'myproject/fileaccess/input.php'; //    MyProject\FileAccess\Input  $input = new MyProject\FileAccess\Input(); 

Absolute name


Full and incomplete names are used in relation to the namespace in which you are currently located. They can only be used to define access at this level or dive deeper into the namespace hierarchy.

If you want to access a function, class or constant that is at a higher level in the hierarchy, then you need to use the full name — an absolute path, not a relative path. The call must begin with a backslash. This allows PHP to understand that this call should be made from global space, and not refer to it relative to your current location.

 <?php namespace MyProject\Database; require 'myproject/fileaccess/input.php'; //    MyProject\FileAccess\Input  //     ,      ,     $input = new \MyProject\FileAccess\Input(); 

We do not need to use the full name for internal PHP functions. Incomplete names for functions and constants will be defined in the global namespace if they are not defined in the current namespace.

Knowing this, we can now overload the internal functions of PHP, while having the ability to call the original function (or constant).

 <?php namespace MyProject; var_dump($query); //  \var_dump($query); //  //       Exception  //      ,    Exception     MyProject\Database           // throw new Exception('Query failed!'); //  ,    ,  ,        throw new \Exception('ailed!'); function var_dump() { echo 'Overloaded global var_dump()!<br />'; } 

Dynamic calls


PHP is a dynamic programming language; so you can use this functionality to call code from the namespace. This is essentially the same as using a dynamic class name or connecting a dynamic file using a variable to store its name. The PHP name separator uses the same meta characters in strings. Don't forget the backslash when you store the name of the namespace as a string!

 <?php namespace OtherProject; $project_name = 'MyProject'; $package_name = 'Database'; $class_name = 'Connection'; //    require strtolower($project_name . '/'. $package_name . '/' . $class_name) . '.php'; //       .        $fully_qualified_name = $project_name . '\\' . $package_name . '\\' . $class_name; $connection = new $fully_qualified_name(); 

Namespace keyword


The namespace keyword is not only used to define a namespace, it can also be used to call in the current namespace, functionally similar to the self keyword for classes.

 <?php namespace MyProject; function run() { echo 'Running from a namespace!'; } // Resolves to MyProject\run run(); // Explicitly resolves to MyProject\run namespace\run(); 

__NAMESPACE__


Just as the self keyword cannot be used to determine the name of the current class, so the namespace keyword cannot be used for the current namespace. Therefore, we use the constant __NAMESPACE__

 <?php namespace MyProject\Database; // 'MyProject\Database' echo __NAMESPACE__; 

This constant is very useful at the beginning of the namespace study; it is also very useful when debugging. Since this is a string, it can be used in conjunction with the dynamic code calls discussed above.

Import or create an alias name


not necessary to use in namespaces

An important feature of namespaces in PHP is the ability to refer to an external absolute name by a pseudonym , or import .

Import is a very useful and fundamental aspect of the namespace. This allows you to use external packages, such as libraries, without worrying about name conflicts. Import is done using the use keyword. If desired, you can specify a custom alias using the as keyword.

 use [name of class, interface or namespace] as [optional_custom_alias] 

How to use it


An absolute name can be attached to a shorter, incomplete name, so you don’t have to write its absolute name every time you want to use it. Nickname creation or import must occur in the parent namespace or in the global. Attempting to do this within a method or function is an invalid syntax.

 <?php namespace OtherProject; // This holds the MyProject\Database namespace with a Connection class in it require 'myproject/database/connection.php'; //         MyProject,      ,         $connection = new \MyProject\Database\Connection(); //   Connection (     ) use MyProject\Database\Connection; //   !     Connection   , PHP    OtherProject\Connection $connection = new Connection(); //    MyProject\Database use MyProject\Database; $connection = new Database\Connection() 

An alternative is the ability to assign an alias with a different name.

 <?php namespace OtherProject; require 'myproject/database/connection.php'; use MyProject\Database\Connection as MyConnection; $connection = new MyConnection(); use MyProject\Database as MyDatabase; $connection = new MyDatabase\Connection(); 

You can also import global classes such as Exception. When importing, you do not have to write its absolute name.

Note that there is no need for an initial backslash for names in the namespace and its presence there is not recommended, since the imported names must be absolute and not processed relative to the current namespace.

 <?php namespace MyProject; // Fatal error: Class 'SomeProject\Exception' not found throw new Exception('An exception!'); // OK! throw new \Exception('An exception!'); //   Exception. use Exception; // OK! throw new Exception('An exception!'); 

Although there is support for dynamic namespace invocation, dynamic import is not supported.

 <?php namespace OtherProject; $parser = 'markdown'; //   require 'myproject/blog/parser/' . $parser . '.php'; //    use MyProject\Blog\Parser\$parser; 

Conclusion


Namespaces are used to avoid clash of definitions and introduce more flexibility and organization into program code. Remember that you are not required to use namespaces; this function is used in conjunction with the object-oriented approach. I hope you consider the possibility of raising your (future) PHP project to a new level by using the namespace.

Source: https://habr.com/ru/post/245893/


All Articles