Escolar Documentos
Profissional Documentos
Cultura Documentos
Namespaces are one of the most significant changes in PHP 5.3. They will be familiar to C# and Java developers, and they are likely to change the structure of PHP applications for the better.
The code following this line will be assigned to the MyProject namespace. It is not possible to nest namespaces or define more than one namespace for the same code block (only the
last will be recognized). However, you can define different namespaced code in the same file, e.g. 1. <?php 2. namespace MyProject1; 3. // PHP code for the MyProject1 namespace 4. namespace MyProject2; 5. // PHP code for the MyProject2 namespace 6. // Alternative syntax 7. namespace MyProject3 { 8. // PHP code for the MyProject3 namespace 9. } 10. ?> Although this is possible, I would advise against it: retain your sanity by defining a single namespace per file. Sub-namespaces PHP allows you to define a hierarchy of namespaces so libraries can be sub-divided. Subnamespaces are separated using a backslash (\) character, e.g.
We can now include this code in another PHP file, e.g. myapp.php 1. 2. 3. 4. 5. 6. 7. <?php header('Content-type: text/plain'); require_once('lib1.php'); echo \App\Lib1\MYCONST . "\n"; echo \App\Lib1\MyFunction() . "\n"; echo \App\Lib1\MyClass::WhoAmI() . "\n"; ?>
No namespace is defined in myapp.php so the code exists in the global space. Any direct reference to MYCONST, MyFunction or MyClass will fail because they exist in the App\Lib1 namespace. To call code in lib1.php, we can add a prefix of \App\Lib1 to define fullyqualified names. The following result is output when we load myapp.php: 1. App\Lib1\MYCONST 2. App\Lib1\MyFunction 3. App\Lib1\MyClass::WhoAmI Fully-qualified names can become quite long and there are few obvious benefits over defining long class names such as App-Lib1-MyClass. Therefore, in the next article, we will discuss aliasing and take a closer look at how PHP resolves namespace names.
How to Use PHP Namespaces, Part 2: Importing, Aliases, and Name Resolution
In part 1, we discussed why PHP namespaces are useful and the namespace keyword. In this article, we examine the use command and the way PHP resolves namespace names. For the purposes of this example, we will define two almost identical code blocks; the only difference is their namespace: lib1.php: 1. <?php 2. // application library 1 3. namespace App\Lib1; 4. const MYCONST = 'App\Lib1\MYCONST'; 5. function MyFunction() { return __FUNCTION__; 6. 7. } 8. class MyClass { 9. static function WhoAmI() { 10. return __METHOD__; 11. } 12. } 13. ?> lib2.php: 1. <?php 2. // application library 2 3. namespace App\Lib2; 4. const MYCONST = 'App\Lib2\MYCONST'; 5. function MyFunction() { return __FUNCTION__; 6. 7. } 8. class MyClass { 9. static function WhoAmI() { 10. return __METHOD__; 11. } 12. } 13. ?> There is a little PHP terminology to understand before we begin Fully-qualified name Any PHP code can refer to a fully-qualified name an identifier starting with the namespace backslash separator, e.g. \App\Lib1\MYCONST, \App\Lib2\MyFunction(), etc.
Fully-qualified names have no ambiguity. The initial backslash operates in a similar way to a file path; it signifies the root global space. If we implemented a different MyFunction() in our global space, it could be called from lib1.php or lib2.php using \MyFunction(). Fully-qualified names are useful for one-off function calls or object initialization. However, they can become impractical when you are making lots of calls. As we will discover below, PHP offers other options to save us from namespace typing cramps. Qualified name An identifier with at least one namespace separator, e.g. Lib1\MyFunction(). Unqualified name An identifier without a namespace separator, e.g. MyFunction().
Although we include both lib1.php and lib2.php, the identifiers MYCONST, MyFunction, and MyClass will only reference code in lib1.php. This occurs because the myapp1.php code is within the same App\Lib1 namespace: result: 1. App\Lib1\MYCONST 2. App\Lib1\MyFunction 3. App\Lib1\MyClass::WhoAmI
Namespace Importing
Namespaces can be imported with the use operator, e.g. myapp2.php: 1. <?php
2. 3. 4. 5. 6. 7. 8. 9.
use App\Lib2; require_once('lib1.php'); require_once('lib2.php'); header('Content-type: text/plain'); echo Lib2\MYCONST . "\n"; echo Lib2\MyFunction() . "\n"; echo Lib2\MyClass::WhoAmI() . "\n"; ?>
Any number of use statements can be defined or you can separate individual namespaces with a comma. In this example we have imported the App\Lib2 namespace. We still cannot refer directly to MYCONST, MyFunction or MyClass because our code is in the global space and PHP will look for them there. However, if we add a prefix of Lib2\, they become qualified names; PHP will search through the imported namespaces until it finds a match. result: 1. App\Lib2\MYCONST 2. App\Lib2\MyFunction 3. App\Lib2\MyClass::WhoAmI
Namespace Aliases
Namespace aliases are perhaps the most useful construct. Aliases allow us to reference long namespaces using a shorter name. myapp3.php: 1. <?php 2. use App\Lib1 as L; 3. use App\Lib2\MyClass as Obj; 4. header('Content-type: text/plain'); 5. require_once('lib1.php'); 6. require_once('lib2.php'); 7. echo L\MYCONST . "\n"; 8. echo L\MyFunction() . "\n"; 9. echo L\MyClass::WhoAmI() . "\n"; 10. echo Obj::WhoAmI() . "\n"; 11. ?> The first use statement defines App\Lib1 as L. Any qualified names using L will be translated to App\Lib1 at compile-time. We can therefore refer to L\MYCONST and L\MyFunction rather than the fully-qualified name. The second use statement is more interesting. It defines Obj as an alias for the class MyClass within the App\Lib2\ namespace. This is only possible for classes not constants or functions. We can now use new Obj() or run static methods as shown above.
The value has obvious benefits during debugging. It can also be used to dynamically generate a fully-qualified class name, e.g. 1. <?php 2. namespace App\Lib1; 3. class MyClass { 4. public function WhoAmI() { 5. return __METHOD__; 6. } 7. } 8. $c = __NAMESPACE__ . '\\MyClass'; 9. $m = new $c; 10. echo $m->WhoAmI(); // outputs: App\Lib1\MyClass::WhoAmI 11. ?>
In PHP 5.3, you can create an instance of a namespaced class. In that situation, the fullyqualified namespace and class name is passed to the __autoload function, e.g. the value of $class_name could be App\Lib1\MyClass. You could continue to place all your PHP class files in the same folder and strip the namespace from the string, however, that could result in file name clashes. Alternatively, your class file hierarchy could be organized in the same way as your namespace structure. For example, a MyClass.php file could be created in the folder /classes/App/Lib1: /classes/App/Lib1/MyClass.php: 1. 2. 3. 4. 5. 6. 7. 8. <?php namespace App\Lib1; class MyClass { public function WhoAmI() { return __METHOD__; } } ?>
A file in root folder could then use the following code: myapp.php: 1. 2. 3. 4. 5. <?php use App\Lib1\MyClass as MC; $obj = new MC(); echo $obj->WhoAmI(); // autoload function
6. function __autoload($class) { 7. // convert namespace to full file path 8. $class = 'classes/' . str_replace('\\', '/', $class) . '.php'; 9. require_once($class); 10. } 11. ?> Explanation: 1. The class App\Lib1\MyClass is aliased as MC. 2. new MC() is translated to new App\Lib1\MyClass() during compilation. 3. The string App\Lib1\MyClass is passed to the __autoload function. This replaces all namespace backslashes with file path forward slashes, and modifies the string so the file classes\App\Lib1\MyClass.php is loaded. I hope you found this series of PHP namespace articles useful. Will you be namespacing in your PHP code?