Categories


Archives


Recent Posts


Categories


PHP Primer: Namespaces

astorm

Frustrated by Magento? Then you’ll love Commerce Bug, the must have debugging extension for anyone using Magento. Whether you’re just starting out or you’re a seasoned pro, Commerce Bug will save you and your team hours everyday. Grab a copy and start working with Magento instead of against it.

No Frills Magento Layout is the only Magento front end book you'll ever need. Get your copy today!

After spending a bit of time poking around a Magento 1 codebase (I still do that — say hi if you need my help), I was reminded that Magento 2 is going to be some developer’s first major experience with PHP namespaces. Beyond Magento, many PHP systems still live in a namespaceless world, and other systems do their best to shield developers from needing to understand namespaces.

The primer below covers the bare minimum you’ll need to know to start working with namespaces in a PHP system that has fully embraced them.

PHP Namespaces: The Basics

Every file in PHP (since version 5.3) “lives” at a certain place in your system or application namespace hierarchy. You, as the programmer, get to decide where a file lives in that namespace hierarchy. For example, the following file

#File: path/to/some/file.php
<?php
namespace My\SpecialNamespace;
//...

lives in the namespace with the name My\SpecialNamespace. That’s a top level “My”, and a second level “SpecialNamespace”. Unlike ruby and python, a file does not automatically get assigned a namespace based on how you include it, or what its file name is.

If you define a class in your file

#File: path/to/some/file.php
<?php
namespace My\SpecialNamespace;
class MyClass
{
}

that class’s full name will be My\SpecialNamespace\MyClass

That is, the entire thing, blackslashes and all, is the class’s full name. This can be a little weird getting used to (especially if you’ve ever worked with a windows file system!). After a few weeks of writing code this way you’ll quickly learn to see backlashes as part of a class’s name.

If you’re working inside your file, you can refer to the class by its short, “local” name

#File: path/to/some/file.php
<?php
namespace My\SpecialNamespace;
class MyClass
{
}

$object = new MyClass;

However, if you were writing code in another file, you’d need to refer to your class by its full name

#File: some/other/file.php
$object = new \My\SpecialNamespace\MyClass;

Another thing to watch out for is using classes in a different namespace. For example, most built-in PHP classes are located in the global top level namespace. For example, if you tried using the following code.

#File: path/to/some/file.php
<?php
namespace My\SpecialNamespace;
class MyClass
{
    public function __construct()
    {
        $test = new DomDocument;
    }
}    
$object = new MyClass;

PHP would yell at you with the following error message

PHP Fatal error:  Class 'My\SpecialNamespace\DomDocument' not 
found in /path/to/some/file.php on line 7        

This seems to be, by far, one of the biggest problems users new to PHP namespaces run into. The problem is when we attempted to instantiate a DomDocument object

$test = new DomDocument;

PHP assumed we wanted a class named My\SpecialNamespace\DomDocument. The same thing that lets us say new MyClass also means we need to be explicit with our other classes. Give the following a try instead

#File: path/to/some/file.php
<?php
namespace My\SpecialNamespace;
class MyClass
{
    public function __construct()
    {
        $test = new \DomDocument;
    }
}    
$object = new MyClass;

In the above code, we’ve told PHP to use the global class DomDocument. That’s not global as in global variables — that’s global as in it’s the “top” of the namespace hierarchy. That’s what the leading \ is for — it lets us use a full class’s name, even if we’re in a different namespace.

If you don’t like the leading \, you have another option. PHP allows you to “import” a specific class into your file. You do this using the use keyword. Consider this last code example.

#File: path/to/some/file.php
<?php
namespace My\SpecialNamespace;
use DomDocument;

class MyClass
{
    public function __construct()
    {
        $test = new DomDocument;
    }
}    
$object = new MyClass;

The code above will run without issue, even though we’re not using a leading backslash with the \DomDocument class name. That’s because we first imported DomDocument into our local namespace with use DomDocument. This will work with any class, not just built-in PHP classes. Consider the Some\Other\Class\Thing class below.

<?php
namespace My\SpecialNamespace;
use Some\Other\Class\Thing;

$object = new \Some\Other\Class\Thing;
$object = new Thing;

Namespaces: The Missing Link

So that’s a very brief overview of namespaces in PHP. If you’re curious, you’ll definitely want to read the manual’s namespace section.. There’s one last thing we didn’t cover, and that’s how PHP namespace related to PHP class autoloading.

In a word — they don’t.

This is a big mental hurdle developers from other languages face when coming into modern PHP. PHP’s namespaces are purely conceptual. They don’t care how you end up includeing or requireing your class definition files.

PHP has, and has had for years, a system called autoloading which allows a developer to define where PHP should load a class from when the developer instantiates an object. This means each framework (Symfony, Zend, Magento) decides how and where a class file is loaded.

While Modern PHP developers have settled into a set of standards (PSR-0 and PSR-4) that define the how and why of PHP autoloading namespace classes, there’s nothing at the language level enforcing this.

Understanding how your framework (or individual components) have implemented their autoload and namespace systems, and how these systems will fit in with your own, is a key skill any PHP developer will need to learn.

Originally published June 27, 2015
Series Navigation<< PHP Primer: Type HintsPHP Primer: Interfaces >>

Copyright © Alan Storm 1975 – 2017 All Rights Reserved

Originally Posted: 27th June 2015