- Bypassing a Slow Composer Repository
- Slow Composer Followup
- Getting Started with PHP Composer and Magento
- PHP: The Right Way; A Review
- PSR and Code Style Guidelines
- Sellvana: Developer’s Alpha Review
- PHP Primer: Type Hints
- PHP Primer: Namespaces
- PHP Primer: Interfaces
- Design Patterns, PHP, and Magento
- PHP-FPM and File Permissions
- Why did the Elephant join the Guild?
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 include
ing or require
ing 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.