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 theMandible
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 returnMandible\Model\Overlay
. - Namespaces and
use
statements are restricted to the current file. This means that even if youinclude
a file withuse
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.