« Using Zend\Loader\Autoloader
What problem does dependency injection solve? »

A primer on PHP namespaces

I know that there are a lot of posts now about namespaces in PHP 5.3. This is mine which is how I learnt how they work.

What are namespaces?

From the PHP manual:

namespaces are a way of encapsulating items

Hardly the most useful of definitions, but it's a starting point! A namespace is a way of grouping code that exists across multiple files without having a naming collision. That is, you can have the same named class in two different places if they are encapsulated within namespaces.

Of course the way that ZF1 solves this problem is with Extra_Long_Classnames which are obviously unique. Namespaces allow us to reference the classname by the important bit (the last section and not have to carry the meta data (where it lives) in every use of the class.

That is, namespaces allow us to:

  • combine libraries with the same classnames
  • avoid very long classnames
  • organise our code easily

Note that namespaces do not just affect classes. They also affect functions and constants.

Defining a namespace

There is a new keyword called namespace which is used to declare a namespace for a file. This is file-wide:

    namespace My\Db\Statement;
 
    class Sqlsrv extends AbstractStatement
    {
    }

Note that we can have multiple sub-namespaces, separated by the backslash. When we extend the Sqlsrv class the extended class is within the namespace too, but not in the same file.

We can then use the class like this:

    $stmt = new \My\Db\Statement\Sqlsrv();

You can have multiple namespaces in a file, but the first namespace must be the first line of code in the file (except comments and declare statements).

Working within the same namespace

When you are working within the same namespace, then any unqualified functions and classes will be resolved to the current namespace. i.e:

    namespace My\Db\Statement;
 
    function testSqlsrv()
    {
        $stmt = new Sqlsrv();
    }

In this case, the SqlSrv class is in the namespace \My\Db\Statement.

Namespace importing: the use keyword

We can import a namespace into a different file using the use keyword.

    namespace My\Application;
 
    use My\Db\Statement;
 
    $stmt = new Statement\Sqlsrv();

Note that we don't use a leading \ in the new statement as we are using a qualified namespace, not a fully-qualified one.

or you can import a specific class from a namespace;

    namespace My\Application;
 
    use \My\Db\Statement\Sqlsrv;
    $stmt = new Sqlsrv();

It follows you can use multiple use statements:

    use \My\Db\Statement;
    use \My\Db\Adapter;
 
    $stmt = new Statement\Sqlsrv();
    $adapter = new Adapter\Sqlsrv();

You cannot do this though:

    use \My\Db\Statement\Sqlsrv;
    use \My\Db\Adapter\Sqlsrv;
 
    $stmt = new Sqlsrv();
    $adapter = new Sqlsrv();

as clearly PHP cannot resolve which Sqlsrv class to instantiate.

You can also alias namespaces. This allows us to reference a long namespace with a shorter name or to import two namespaces having the same name and give them different names.

    use \My\Db\Statement\Sqlsrv as DbStatement;
    use \My\Db\Adapter\Sqlsrv as DbAdapter;
 
    $stmt = new DbStatement();
    $adapter = new DbAdapter();

This also allows you to write code the focusses on the functionality of the class rather than the specific type. For example, we could start using the Mysqli versions of the statement and adapter by just changing the use statements.

The __NAMESPACE__ constant

The constant __NAMESPACE__ provides the current namespace name. In the global space it will be an empty string.

Namespace resolution

This bit is really important!

An unqualified class name is resolved in this order:

  1. If there is an import statement that aliases another name to this class name, then the alias is applied.
  2. Otherwise the current namespace is applied.

An unqualified function name has different rules:

  1. The current namespace is prepended to the function name.
  2. If the function names doesn't exists in the current namespace, then a global function name is used if it exists.

This means that within a namespace'd file, you can do:

    $date = date('Y-m-d');

but not:

    $datetime = new DateTime();

Instead, you have to use:

    $datetime = new \DateTime();

Conclusion

That's really all you need to know to use namespaces in a PHP application. They aren't so hard really.

Like this article?
  • Tweet

This entry was posted on Thursday, 16th February 2012 at 08:25 and is filed under PHP.

6 Responses to “A primer on PHP namespaces”

  1. 1 Rob...
    February 16th, 2012 at 09:33 #

    Thanks to all the people who pointed out the missing \ in the last code sample. For some reason, I have to escape every backslash in code blocks on this blog and I missed that one.

  2. 2 Gerard
    February 16th, 2012 at 15:32 #

    There may well be a lot of posts about namespaces, but it's surprising how confusing many of them are. This is nice and concise.

    A couple of things:

    Under "Defining a namespace" the namespace is "Zend", should be "My".

    Also, in the same section I'd expand upon the statement "the first namespace must be the first line of code in the file" with a note that comments are allowed.

    One more, re: "In this case, the SqlSrv class is in the namespace"
    The namespace that follows is double slashed, should only be single slashed.

  3. 3 Rob...
    February 16th, 2012 at 15:39 #

    Thanks Gerard :)

  4. 4 C. Daniel Chase
    February 17th, 2012 at 13:59 #

    Rob, I'll second Gerard with his comment on this post being a nice concise description of namespaces.

    Considering your well used Zend Framework Tutorial and work in general, do you have any advise on applying namespaces in a ZF application? I realize this will probably change with ZF2, but I'm developing a ZF1 application and would like to hear some thoughts on how namespaces could effectively be used to eliminate some of the long cumbersome class references.

    Thanks! -Dan

  5. 5 John Congdon
    February 17th, 2012 at 14:19 #

    Thank you for this post. I just changed some of the newer code that I have written in the past week to use namespaces.

    They weren't too hard to implement, just had to be diligent. Thanks to having unit tests, it made it very easy for me to make sure they all still worked.

    Rob, you are a gentleman and a scholar. Thanks again!

  6. 6 Matt
    February 18th, 2012 at 06:41 #

    Thanks for the explanation. However, one question I keep having while reading about namespaces and haven't found answered (well enough), is the why. Why use them? Or when are they an advantage?

    Looking at the examples you gave in this article, it only seems to make the code harder to work with. Instead of having one word which specifies exactly which class I'm dealing with (say A_Db_Adapter_Mysql), I have to split that up in two lines. And then when there's a usage of the Mysql later in the code (say new Mysql) I can't know which class that is without going to the top of the file and looking which namespace it is in.

    I'm sure there are advantages of using them, but I just haven't seen them explained well enough yet. Or maybe the kind of code I work with isn't the kind of situation namespaces have advantages.

The views expressed in these comments are not the views of the publisher. However, we believe in the rights of others to express their legitimate views and concerns. Any legitimate complaint emailed to rob@akrabat.com will be seriously considered and the post reviewed as desirable and necessary.

gipoco.com is neither affiliated with the authors of this page nor responsible for its contents. This is a safe-cache copy of the original web site.