PHP Keywords: namespace

13 March 2019 - 7:30am

Welcome to my series on every PHP keyword and its usage. Today's item: namespace.

The problem

Every time you define a class, function or constant in the global scope, you define one more name that you can't use again. This is typically fine in your own code, it's easy enough to come up with a different name, if you've already used one before. But what about when you want to use someone else's library? Or multiple libraries? What happens when there's a conflict?

The simple answer to this is for everyone to give all their definitions overly long names, like MandibleModelOverlay. But throwing around large names like this is a lot of effort and can damage code legibility.

The solution

Enter namespaces. They work like this: First you define your namespace:

<?php
namespace Mandible;

class ModelOverlay{}

And then you can use it from elsewhere in your code:

<?php
$overlay = new Mandible\ModelOverlay();

The use statement

You may have noticed one problem. You're still writing just as much code every time you want to use something defined in another namespace.

<?php
use Mandible\ModelOverlay;

$overlay = new ModelOverlay();
$overlay2 = new ModelOverlay();

If you already have a class with that name, you can alias it to something else:

<?php
use Mandible\ModelOverlay as MandibleOverlay;

$overlay = new MandibleOverlay();

Multi-level namespaces

Namespaces can be many levels deep, not just one.

<?php
    namespace Mandible\Model;

    class Overlay{}
<?php
    use Mandible\Model\Overlay;

    $overlay = new Overlay();

Multi-namespace files

Typically, a namespace and any use statements are defined for an entire file. It's discouraged, but possible, to use multiple namespaces in a single file however:

<?php
namespace A;
// Code goes here

namespace B;
// Code goes here

Alternatively, one can use braced style. Braced style is preferred, since it's clearer, and it's possible to use the global namespace when using the braced style:

<?php
namespace A
{
    // Code goes here
}

namespace B
{
    // Code goes here
}

namespace
{
    // Global code goes here
}

Accessing different namespaces

Namespaces work a little like directories. From within a namespace, you can call other definitions within that namespace without defining the entire namespace:

<?php
namespace Mandible\Model;

class SpecialOverlay extends Overlay{}

However, in order to access other namespaces, you need to provide a relative or absolute path.

  • Use statements are always absolute, so they do not need to start with a \. Other absolute paths do, else they will be interpreted as a relative path.
  • You can only provide a relative path to a more complex namespace, so new Model\Overlay() is possible from the Mandible namespace.
  • If a function can't be found in the current namespace, PHP will call the global namespace. This is only true for functions, global classes must be called using an absolute path.
<?php
namespace Mandible;

// Fully qualified, absolute class name
$overlay = new \Mandible\Model\Overlay();

// Relative class name
$overlay = new Model\Overlay();

// Calling a global function
$time = time();

// Calling a global class
$date = new \DateTime();

Other notes

  • When you use the ::class magic constant on an object from a namespace, it will give the entire namespace. e.g. Overlay::class will return Mandible\Model\Overlay.
  • Namespaces and use statements are restricted to the current file. This means that even if you include a file with use statements, you won't have access to any of their aliases.
  • It's common practice to match namespaces to your folder structure. If you use autoloading (either your own, or provided by something like Composer), it is trivial to convert a fully qualified classname into a directory structure.