PHP Namespaces

Namespaces were a long awaited feature in PHP. While many other important features were released with PHP 5, namespaces were not supported until version 5.3. This led to various techniques for emulating them which, though necessary, were messy and confusing. Although namespaces have been part of PHP for over a year now, such techniques still exist. Many developers simply don’t know how to use proper namespaces in their code. In this article I will explain why namespaces are important and how you can use them in your own PHP code.

Why Use Namespaces?

Imagine you work for a small company that doesn’t have many employees. When talking about a co-worker, you refer to him by his first name. After an exceptionally successful year, your boss decides to double the number of employees. Suddenly, when you mention “Tom,” people are no longer sure to whom you are referring since there now a number of Toms at the office. To differentiate between them, you start using their last names too.

This metaphor illustrates the concept of namespaces. A namespace is a named container for identifiers such as class names and function names that you use in your programs. It groups them together and removes the possibility of name-clashes. In the example, the employees’ last names served as namespaces. Because family members are often grouped together, multiple Toms are able to co-exist without any ambiguity.

Large applications often have hundreds or thousands of components, which lead to a large number of name-clashes. Namespaces allow you to elegantly group components and avoid this problem.

Before namespaces were available, developers emulated them in object-oriented code by prefixing each component’s classes with a component name. For example, one standard was to join component and class names using underscores; the mail class in the blog component was named Blog_Mail. This practice led to many long, and sometimes confusing, class names. Consider the name of a class in the PHPUnit framework, PHPUnit_Framework_MockObject_Matcher_StatelessInvocation. This obviously isn’t ideal, which is why programmers needed proper support for namespaces in PHP.

Defining Namespaces

A namespace is defined with the namespace keyword and a name. It must be declared before any other code, with the exception of rarely used declare statements. Once defined, the scope of the namespace applies to the entire file.

<?php
namespace MyNamespace;
// ...

A namespace may alternatively be defined by wrapping brackets around its contents. No code is allowed outside the brackets except for the previously mentioned declare.

<?php
namespace MyNamespace {
    // ...
}

These two methods cannot be mixed, so choose one and stick to it.

Nested namespaces can be defined by separating each level with a backslash.

<?php
namespace MyProject\Blog\Admin;

Multiple namespaces may be defined in a single file by using the namespace keyword multiple times. In such instances, the scope of the preceding namespace ends once the next namespace definition appears.

<?php
namespace MyProject\Blog;
// following definitions are part of the MyProject\Blog namespace
// ...
namespace MyProject\Store;
// following definitions are now part of MyProject\Store
// ...

To set part of the file’s code in the global namespace, use the namespace keyword without a name. This feature can only be used in conjunction with the curly bracket syntax.

<?php
namespace My\Project {
    // My\Project namespace
    // ...
}
namespace {
    // Global namespace
    // ...
}

Referencing Namespaced Identifiers

Although any code can appear within the namespace, only classes, interfaces, functions and constants are affected by it. These identifiers can be referenced in one of three ways:

  1. Fully-qualified name
    A fully-qualified name is like an absolute path in a file system. It is the full name of the identifier; therefore there is no ambiguity about which identifier is being referenced. Fully-qualified names begin with a backslash. For example, My\Foo\Bar looks for the class Bar in the namespace My\Foo.
  2. Qualified name
    A qualified name is like a relative path in a file system. It contains only part of the name and resolves relative to the current namespace. For example, Foo\myFunction() in the namespace MyBaz resolves to \My\Baz\Foo\myFunction().
  3. Unqualified name
    An unqualified name is identical to a qualified name except it refers to the current namespace only and not to any sub-namespaces. For example, getPosts() in the namespace My\Foo\Blog resolves to Blog\getPosts(). If a function or constant is not found in the current scope, PHP won’t look for \My\Foo\getPosts(), rather it will just resolve the identifier to the global namespace.

Let’s look at an example. file1.php contains a couple of mock definitions namespaced as \MyProject\Blog.

<?php
namespace \MyProject\Blog;
class myClass {}
function myFunction() {}

Now file2.php declares the MyProject namespace, includes file1.php, and defines mock definitions that would seemingly conflict. The definitions don’t, though, because they live in separate namespaces. Then the file goes on to show examples of how fully-qualified, qualified, and unqualified names are resolved.

<?php
namespace \MyProject;
require_once "file1.php";
class myClass {}
function myFunction() {}

// fully-qualified names
\MyProject\myFunction();
\MyProject\Blog\myFunction(); 

// qualified name
\Blog\myFunction(); //resolves to \MyProject\Blog\myFunction();

// unqualified name
$test = new myClass(); // resolves to \MyProject\myClass
myFunction(); // resolves to \MyProject\myFunction

Notice that to reference classes and interfaces in the global namespace, you must begin their names with a backslash, i.e., use their fully-qualified name. This is not required for functions and constants unless an identifier with the same name is found in the current scope. To illustrate this, consider the following example:

<?php
namespace \Foo\Bar;
function file_exists($filename) { return true; }

// Incorrect: "Fatal error: Class '\Foo\Bar\ArrayObject' not found..."
$obj = new ArrayObject();
// Correct
$obj = new \ArrayObject();

// Doesn't need backslash; resolves to native function
echo strlen("Hello, world!");
// Resolves to dummy function, \Foo\Bar\file_exists()
echo file_exists('non-existent-file'); // True
// Resolves to real function
echo \file_exists('non-existent-file'); // False

The use Keyword

In a large application that contains many, deeply-nested namespaces, it can become cumbersome to write out identifier names. To avoid this, you can import namespaces, classes and interfaces using the use keyword. This allows them to be referenced by an alias instead of their full name. use statements must be declared in the outermost scope of the file.

Here is an example:

<?php
use \Very\Long\Namespace;
use \Another\Long\Namespace\ClassName;

// resolves to \Very\Long\Namespace\aFunction();
Namespace\aFunction();
// resolves to \Another\Long\Namespace\ClassName
$obj = new ClassName();

Only unqualified and qualified names are affected by aliases; fully-qualified names are not. Therefore, the following will not be affected by the defined aliases:

<?php
$obj = new \ClassName();

To specify a specific alias, use the as keyword followed by the alias.

<?php
use \Very\Long\Namespace as MyNamespace;
// resolves to \Very\Long\Namespace\ClassName
$obj = new MyNamespace\ClassName();

For convenience, PHP lets you separate multiple namespace declarations with commas.

<?php
use \Very\Long\Namespace as MyNamespace,
    \Another\Long\Namespace\ClassName;

To explicitly use the current namespace and avoid aliases, use the namespace keyword before the identifier name.

<?php
// resolves to current namespace, not \Another\Long\Namespace\ClassName
$obj = new namespace\ClassName();

Dynamic Features

PHP offers some support for using namespaces dynamically, as well. The magic __NAMESPACE__ constant is defined by PHP at compile time and contains the current namespace as a string. In the global namespace, __NAMESPACE__ contains an empty string.

Namespaced identifiers can be dynamically referenced just like normal identifiers, with one exception: identifiers can only be referenced using fully-qualified names. For example:

<?php
$class = '\MyProject\Blog\MyClass';
$obj = new $class();

You should always escape backslashes when they are in double-quoted strings, since certain character combinations have special meanings. For example, “n” is the newline character, “t” is the tab character, etc. Failing to do so can lead to unexpected results. For example, the following code will not work as expected:

<?php
// "\n" in "\newFunction" seen as newline
$function = "\MyProject\Blog\newFunction";
$function(); // Fatal error: "Call to undefined function..."

The correctly escaped string is "\\MyProject\\Blog\\newFunction".

Summary

Namespaces are a powerful language feature that can be used to effectively group components in an application without fear of collision. This article covered the reasons why you should use namespaces and the syntax for defining and using them. You also saw how the use keyword allows you to alias namespaces, and how to use namespaced classes and functions dynamically. Now you should have a complete understanding of namespaces and be ready to start using them in your own applications.

Win an Annual Membership to Learnable,

SitePoint's Learning Platform

  • Aaron Osteraas

    If I can read and understand namespaces from this, anyone can.

    Excellent job.

    • http://w3cafe.net Abdullah Al Mamun

      Excellent comment :)

  • EllisGL

    I believe a good directory structure and a good auto loader really solved this issue before and is a lot simpler.
    $x = new johnny_monkey_printer();

    • EllisGL

      Also if you are complaining about long underscored names, think of this, you can read it, you know what it is. I have:
      use JohnnyMonkey;
      use WolfTree;

      $x = new Printer();

      Well then you have to figure out which of the namespaces that Printer came from.

      • http://www.jamestitcumb.com James

        EllisGL:

        The correct code for your example should be:

        use JohnnyMonkeyPrinter;
        use WolfTree;

        $x = new Printer();

        For objects you must “use” the class name. You can alias a namespace and use that though:

        use JohnnyMonkey as Monkey;
        use WolfTree;

        $x = new MonkeyPrinter();

        It’s all in the article!

      • dan

        In your case it came from the global namespace.
        Otherwise, you have to write MonkeyPrinter() or TreePrinter()

    • Moshe Teutsch

      I agree with you that it is possible to emulate namespaces without much difficulty, but namespaces provide a number of benefits. For example, you can alias and import them with the “use” keyword and save yourself some typing. Also, you easily references classes within the same namespace. They even allow you to neatly namespace functions and constants.

      In my opinion, it is always better to use the native solution because 1) it is more transparent, and 2) it usually provides additional features. You might as well argue that “define” is too expensive and that you should just use uppercase ($ALL_UPPERCASE) variables instead of constants.

  • Headbank

    Useful article; I’ve been writing namespaced classes like billy-o since PHP 5.3 appeared (with a good __autoload function, it also means I can keep them in a nice semantically-equivalent folder hierarchy) but my interpretation of the manual was that all native functions had to be backslash-prepended in this context. It’ll be nice to stop worrying about that :)
    I would advise though that it seems to be necessary in some circumstances to use double-backslashes with single-quoted strings too, when doing dynamic classname assignment. Not sure why this is, but I’ve found it’s better safe than sorry.
    PS – this site is a bit of a horror with Javascript disabled … your cousins at Sitepoint would be shocked at the lack of progressive enhancement!

  • Thomas Jane

    Are they like packages in Java?

  • http://AIR--TRAVEL.COM Brisa Henke

    I really enjoy the post.Really thank you! Really Cool.

  • http://kahancreations.com Amit SIdhpura

    Thanks! I really needed such article to start learning Zend Framework 2.0

  • Koushik

    Very good article

  • http://www.isbahtoday.com Inayatullah

    Article is good but you didn’t discuss that how many benefits we can achieve from namespaces

    • bksunday

      Useful when not creating everything you use. You can for example handle part of your php code with an outside library and forget about variables, classes and functions name collisions or unexpected behaviors. Helps organize code too!

  • Jon

    Very good article. Explanations almost anyone can follow.

  • http://www.dhavalpatel.info Dhaval Patel

    Very nice article. Thanks.

  • TimVS

    I just started working with Symfony 2.1. This post about namespaces realy helped me.
    Thanks

  • Vinod Dalvi

    It is really a good article…!!!!

  • http://blog.agung-setiawan.com Agung Setiawan

    good article, but because i am a Java developer, compared to Java, the concept of namespace in PHP is a little bit weird hahaa…
    just my 2 cents

  • Hassan info

    good article.
    namespace in PHP very useful

  • Jure

    I got a good grasp of what Namespaces are all about and considering 15 min ago, before reading this article, i didnt have a clue what they stood for.

    Cheers for a good article !

  • Asi_x

    Great Article, really very helpful for me to understand namespace concept. Thanks a lot