PHP namespaces are almost ten years old. Yes, a decade has passed (and yes, you’re getting old). Despite a decade passing by since PHP v5.3 was released many developers still don’t have a basic understanding of namespaces. Truth be told WordPress doesn’t use namespaces so “you don’t need to know how to use namespaces if you only work with WordPress.” You don’t need to be a namespace ninja but getting a grasp on the basics is simple and does you good.
When there’s no namespace support – use a prefix
For a long, long time PHP didn’t have native namespace support. That’s why WordPress and a lot of other big codebases don’t use native namespaces. They weren’t around when needed, so prefixes are used.
Namespacing is important because it makes sure your function write_to_log()
hasn’t already been defined by another piece of code. To avoid name clashing everything in global scope needs a prefix so the function becomes awesome_project_write_to_log()
and all other functions and variables get the awesome_project_
prefix too. Simple? It is! Pretty? Not exactly.
There are some alternatives to that approach like the static methods encapsulation. You wrap all of your functions in a class and declare them as static methods. Then instead of calling my_function()
you call My_Class::my_function()
. Better? A bit, but still not proper namespacing.
Let’s see how namespacing allows for multiple code pieces (or packages if you want) to use the same class and function names without conflict. Or as the PHP manual says – how they enable code encapsulation. Their analogy with files and folders is also spot on – in a lot of ways namespaces behave just like folders, so I’ll copy/paste from the manual;
In any operating system, directories serve to group related files and act as a namespace for the files within them. For instance, the file foo.txt can exist in both directory /home/greg and in /home/other, but two copies of foo.txt cannot co-exist in the same directory. To access the foo.txt file outside of the /home/greg directory, we must prepend the full directory name to the file name using the directory separator to get /home/greg/foo.txt.
Declaring namespaces – remember the first line
The keyword namespace
has to be the first line of code in the file (not counting comments and any non-PHP content). Namespaces affect only classes, interfaces, functions and constants. They do not affect variables. You can define the same namespace in multiple files allowing you to split code into multiple files. Sub-namespaces allow for defining a hierarchy in namespaces much like in folders by using a backslash – namespace myproject\level1\level2
. Those are basic and almost all rules for declaring namespaces.
// file-A.php contains a function under the myCompany\PackageA namespace namespace myCompany\PackageA; function do_something() { // do things }
// file-B.php contains a function with the same name // but under a different namespace namespace myCompany\PackageB; function do_something() { // do things }
Although possible, I’d highly recommend not combining multiple namespaces into a single file. Trust me, sooner or later you’ll forget you did it and then debugging a 2-minute bug takes two hours. However, if you must, here’s the syntax.
// do not put multiple namespace declarations into the same file // but if you must, here's the syntax namespace MyFirstProject { const CONST = true; class Connection { /* ... */ } function connect() { /* ... */ } } namespace MySecondProject { const CONST = true; class Connection { /* ... */ } function connect() { /* ... */ } } // any code after this has to go in the global namespace namespace { $some_var = 1; function_in_global_namespace(); }
Using namespaces – remember folders
As I already said – namespaces are extremely similar to folders. Assuming file foo.txt
is in your current folder; you can reference it with a simple foo.txt
. If you’re one level above the folder with foo.txt
file then you need to use a relative path ../foo.txt
or an absolute one /folder1/folder2/foo.txt
. Nothing fancy. Namespaces use the same paradigm.
// remember after declaring a namespace // all our code is in it; like when you're working in a folder namespace mycompany\project; function foo() {} class foo { static function staticmethod() {} } // resolves to mycompany\project\foo() because of line #3 foo(); // likewise, resolves to mycompany\project\foo::staticmethod() foo::staticmethod(); // constant are affected by namespaces too // so we're working with mycompany\project\FOO echo FOO; // this is a relative path // resolves to mycompany\project\subnamespace\foo() subnamespace\foo(); // static methods are no different // mycompany\project\subnamespace\foo::staticmethod() subnamespace\foo::staticmethod(); // a full namespace path starts with a backslash // it resolves exactly to what it says it does \otherNamespace\Bar\foo(); // again same thing for a constant, full path nothing magical echo \otherNamespace\Bar\FOO;
Have a look at the use
keyword in the PHP manual – examples are great. It provides a way to import code from other PHP namespaces into the current namespace or to refer to an external (fully qualified) name with an alias.
Yes, you need namespaces & should use them
As it’s more than evident by looking at WordPress’es source – you don’t have to use namespaces, but you do have to use some method of namespacing. Prefixing with wp_
in WP’s case. So if we’re already doing it why not do it properly?
Namespaces in PHP easily integrate into any development workflow. They ease autoloading, file naming and in general make the code cleaner. Refactoring old code is never a popular task (regardless of the coding language) so I’m not going to tell you to go ahead and refactor a working 2 MB project just so that you can say you use namespaces. However, I’m going to insist you use namespaces when working on new projects. You’ll thank yourself soon enough.
Official PHP documentation on namespaces is beyond excellent! Code samples are clean and comments real-world helpful. Be sure to browse it, even if you don’t think you need to.