PHP Namespace Primer

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

Commerce Bug 2.5: One Click Layout Graph

Like this article? 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.

Just a quick note that Commerce Bug 2.5 is out, official boring press release-ish announcement here, free upgrade for registered users, and a screencast of the one new feature below.

I know Magento 2 is the new hotness, but Magento 1 sites will be with us for long time. Commerce Bug remains a programmer’s best weapon against the insane complexity of most half-assed Magento implementations that your business development folks foist on you. If you haven’t bought your copy yet, it’s your funeral.

Some Notes on Graph Rendering

Commerce Bug has long had the ability to create a text version of a directed graph of the layout. If you knew about programs like Graphviz, this was a super useful feature for quickly understanding a page’s layout structure.

Unfortunately, lots of developers don’t know about programs like Graphviz, and not all of Commerce Bug’s buyers are developers. Even for folks who do know about Graphviz, the process of copy/pasting the graph text into a file and then rendering that file created friction. Layout graphs were/are a super useful feature, but the initial implementation was lacking.

Tree vs. Graph

The high level solution is obvious — handle rendering the layout in Commerce Bug itself. Coming up with the right implementation for this feature, however, was more difficult that I first imagined.

Magento’s layout is often described as a series of nested block objects. If this were 100% true, a UI/visualization would be simple. Just grab one of the many javascript tree layout implementations and call it a day.

Unfortunately — while Magento’s layout is a series of nested block objects, it’s a self modifying series of nested block objects. This means that

  1. Magento creates a tree of block objects, and starts rendering the root block

  2. When every block renders, it can potentially create its own blocks

  3. When every block renders, it can potentially add, remove and move blocks in the layout

This means every block doesn’t always have a clear parent block, or a single parent block. These are more than theoretical concerns. Either via deliberate developer cleverness, or via the inevitable result of hiring 1,000 monkeys to bang on a keyboard until a store falls out the other end, all of these scenarios are common in production Magento systems.

This means a standard tree UI wouldn’t be an accurate representation of the layout. If this were a corporate driven project like Z-Ray, I’d probably have just shipped the tree UI and called it good enough. However, people don’t buy Commerce Bug because it checks a feature off a list — they buy Commerce Bug because it actually makes working with Magento easier.

This dilemma is what led me to using a directed graph in the first place. The language of a graph allows me to come up with an accurate layout visualization that clarifies Magento’s layout without resorting to oversimplifications or computer lies.

Finding a Graph Renderer

Development being one dilemma sprouting multiple new dilemma, this meant I needed to find a way to render a directed graph in a browser. While graphs are one of the first problems industrialized computer science set out to solve, and there’s lots of code out there that makes sense of graphs, little of that code has made it’s way into a form reasonably and easily consumable by the average web browser.

There’s lots of libraries that model directed graphs (nodes, edges, the relationships between them) without actually providing a visualization layer. Visualization layers do exist, but they tend to be focused on flashy animations or high level views of huge data sets without providing a good UI for analyzing the specifics of the graph. There’s even a few <canvas/> renderers, but performance of these was abysmal, and the UI/UX problem of navigating a large graph still exists.

At the end of the day, the best visualizers were desktop applications like Graphviz, or converting the graph to a neutral format (gif, SVG, PDF, etc.) and using a separate tool to view the graph.

Deciding on a Webservice

Interestingly, possibly ironically, and certainly tangentially, it was Zend’s new Z-Ray extension that provided me with the final bit of convincing that a web service graph renderer was the right approach.

There’s lots of smart people working on Z-Ray, but it’s ultimately a corporate product, and a corporate product will never be able to go as deep as framework specific debugging extensions. Z-Ray may have a great Symfony plugin, but that plugin will never be as good as the native Symfony debugger.

That said — once advantage Z-Ray does have is in-depth platform insights. While it only runs on systems using the Zend Server platform, that deep platform integration gives them insights into what people are actually doing with the platform. This means Z-Ray has Zend Server specific features that no one else can match.

That sort of insight is one of the less talked about benefits of cloud based platforms. Shifting corporate examples, a company like New Relic doesn’t need to ship a perfect monitoring platform out of the gate — they can ship a pretty good monitoring platform and then adjust it as they get real feedback from real users using the system.

Up until now I’ve been very wary of getting into independent application service provider, software as a service, cloud platform development. I’ve always modeled my projects on the desktop software model, in particular the Mac OS software model. Deliver people a set of bits that help them do their job — deliver the right bits and you’re selling cost free widgets. I still believe in that model, but not taking advantage of what a cloud based platform can do is hurting my users, and ultimately hurting my business.

So, in addition to giving my Commerce Bug users the ability to instantly render a layout graph — Commerce Bug 2.5 is me dipping my toe in the cloud computing pool. For now I’m keeping rendering free of any monthly costs, but that may change if hosting costs start becoming a burden.

As always, thank you for reading, and thank you for buying the digital products I create. Those sales directly fund my writing here, and I’m forever grateful for what they do for my career.

Originally published May 2, 2015

Laravel 5 Autoloader

Like this article? 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.

Last time we finished up our look at Laravel 4.2’s autoloader implementation. Like a lot of features in Laravel, (or any framework), once you pull out the microscope sharp edges begin to jut out everywhere.

However, unlike many other framework teams, the Laravel core team is willing to make shifts in their platform and application architecture. If you’re familiar with the internals of Laravel 4, looking at the internals of Laravel 3 may be a little disorienting. Similarly, the recent release of Laravel 5 presents some new wrinkles at the system level.

Today we’re going to examine changes to the autoloader in Laravel 5, and how they address some of the issues and edge cases we encountered when exploring Laravel 4.2’s autoloader.

Laravel 5 Registered Autoloaders

The first thing we’ll want to do is examine which autoloaders Laravel registers in a typical Laravel 5 HTTP request. One way to do this is to add the following route definition (note the new app/Http/routes.php location in Laravel 5)

#File: app/Http/routes.php
Route::get('/show-autoloaders', function(){
    foreach(spl_autoload_functions() as $callback)
    {
        if(is_string($callback))
        {
            echo '- ',$callback,"\n<br>\n";
        }

        else if(is_array($callback))
        {
            if(is_object($callback[0]))
            {
                echo '- ',get_class($callback[0]);
            }
            elseif(is_string($callback[0]))
            {
                echo '- ',$callback[0];
            }
            echo '::',$callback[1],"\n<br>\n";            
        }
        else
        {
            var_dump($callback);
        }
    }
});

This code loops over each registered autoloader, and attempts to echo back something sane, (based on the sort of callback registered). With the above code in place, if you load the following URL in your application

http://laravel5.example.com/index.php/show-autoloaders

You’ll see the following output

- Illuminate\Foundation\AliasLoader::load 
- Composer\Autoload\ClassLoader::loadClass 
- PhpParser\Autoloader::autoload 
- Swift::autoload 

So, right off the bat we see some familiar friends. The AliasLoader::load method is still lazy loading Laravel’s aliases. The Composer ClassLoader::loadClass method is still taking care of Composer’s four autoloading methodologies, and the Swift::autoload method is still there, taking care of its legacy duties.

The first change that pops out is the addition of the PhpParser\Autoloader::autoload method. However, more significant than that — Laravel’s native Illuminate\Support\ClassLoader::load is gone! This is, by far, the most significant change to the autoloader architecture in Laravel 5. Instead of the dueling Composer and Illuminate autoloaders, Laravel’s thrown all its autoloading eggs in the Composer basket. We’ll talk more about the impact of this below, but first let’s get a quick explanation of the PhpParser\Autoloader::autoload method out of the way.

PhpParser Autoloader

The PhpParser project is a third party library for creating an abstract syntax tree for PHP files, and is implemented in PHP itself. If that didn’t make sense, it’s a library that makes writing code analysis tools simpler. Laravel itself doesn’t use the PhpParser library for anything, but libraries that Laravel does use have PhpParser listed as a dependency, and this autoloader comes along for the ride.

If we look at the autoload section in the PhpParser composer.json file

#File: vendor/nikic/php-parser/composer.json
"autoload": {
    "files": ["lib/bootstrap.php"]
},

we see that PhpParser uses the files autoloader type to include the following file

#File: vendor/nikic/php-parser/lib/bootstrap.php
require __DIR__ . '/PhpParser/Autoloader.php';
PhpParser\Autoloader::register();     

As you can see, unlike most of the other files autoloaders we’ve seen, PhpParser actually uses the files autoloader for its intended purpose — registering an autoloader. If we take a look at the PhpParse\Autoloader::autoload method itself

#File: vendor/nikic/php-parser/lib/PhpParser/Autoloader.php    
static public function autoload($class) {
    if (0 === strpos($class, 'PhpParser\\')) {
        $fileName = dirname(__DIR__) . '/' . strtr($class, '\\', '/') . '.php';
        if (file_exists($fileName)) {
            require $fileName;
        }
    } else if (0 === strpos($class, 'PHPParser_')) {
        if (isset(self::$oldToNewMap[$class])) {
            self::registerLegacyAliases();
        }
    }
}

we see a standard autoloader and a bit of legacy code handling.

The first conditional checks if the requested class is prefixed with PhpParser\\, and if so, converts the namespace class name into a file path, and then requires the file. This is the standard autoloader.

The second block of the conditional checks if the class is prefixed with PHPParser_ — i.e., if it’s a class in the global namespace. If so, and the class name exists as a key in self::$oldToNewMap, the autoloader calls the registerLegacyAliases method, which looks like this

#File: vendor/nikic/php-parser/lib/PhpParser/Autoloader.php 
private static function registerLegacyAliases() {
    foreach (self::$oldToNewMap as $old => $new) {
        class_alias($new, $old);
    }
}

This is a clever bit of refactoring help that’s probably best explained with an example. Let’s say there’s some old code out there that looks like this

$builder = new PHPParser_Builder;

When the PhpParser team wanted to modernize and use classes with namespaces, they could have easily changed

class PHPParser_Builder
{
}

to

namespace PHPParser;
class Builder
{
}

and left it at that.

However, this means anyone using old code like $builder = new PHPParser_Builder would suddenly have a breaking application. That’s where registerLegacyAlias comes into play

#File: vendor/nikic/php-parser/lib/PhpParser/Autoloader.php        
private static function registerLegacyAliases() {
    foreach (self::$oldToNewMap as $old => $new) {
        class_alias($new, $old);
    }
}

This method runs through every entry in the self::$oldToNewMap array

#File: vendor/nikic/php-parser/lib/PhpParser/Autoloader.php        
private static $oldToNewMap = array(
    'PHPParser_Builder' => 'PhpParser\Builder',
    'PHPParser_BuilderAbstract' => 'PhpParser\BuilderAbstract',
    'PHPParser_BuilderFactory' => 'PhpParser\BuilderFactory',
//...               

and registers an alias for the old-style class

#File: vendor/nikic/php-parser/lib/PhpParser/Autoloader.php        
class_alias('PhpParser\Builder','PHPParser_Builder');      

In plain english? If a user uses the old-style PHPParser_ classes, the PhpParser autoloader will automatically alias that old-style class to a new-style class, and the legacy code will continue to work without any changes. (PHP will automatically attempt to autoload the first argument you pass to class_alias).

Nothing too out of the ordinary here — just another stand-alone pre-PSR autoloader doing its thing.

Composer Only Autoloading

The bigger change in Laravel is the move to Composer only autoloading. To get our heads around this, we’ll want to look at the stock Laravel application composer.json autoloading sections

#File: composer.json
"autoload": {
    "classmap": [
        "database"
    ],
    "psr-4": {
        "App\\": "app/"
    }
},
"autoload-dev": {
    "classmap": [
        "tests/TestCase.php"
    ]
},

as well as the Laravel framework composer.json

#File: vendor/laravel/framework/composer.json
"autoload": {
    "classmap": [
        "src/Illuminate/Queue/IlluminateQueueClosure.php"
    ],
    "files": [
        "src/Illuminate/Foundation/helpers.php",
        "src/Illuminate/Support/helpers.php"
    ],
    "psr-4": {
        "Illuminate\\": "src/Illuminate/"
    }
},

The first, and biggest change? Most classes in Laravel are now loaded with Composer’s psr-4 autoloader. For the framework code, this means Composer loads Illuminate\\ prefixed classes

#File: vendor/laravel/framework/composer.json
"psr-4": {
    "Illuminate\\": "src/Illuminate/"
}

from the following folder

vendor/laravel/framework/src/Illuminate/

Previously, the Laravel framework code used a psr-0 autoloader to do the same thing.

More radical is the introduction of the App namespace for application classes. Thanks to this bit of configuration

#File: composer.json
"psr-4": {
    "App\\": "app/"
}   

Composer will look for any class prefixed with App\\ in the app/ folder off the root of the project. This is combined with a major overhaul of how a Laravel 5 application works. When you create a Laravel 5 application

$ laravel new my-project

Laravel will automatically create a number of App\\ prefixed classes that make up your application. These changes could be an article in and of themselves, but here’s one example that demonstrates The New One True Way™.

In Laravel 4.2, if you wanted to register a new artisan command class, you’d edit a simple PHP include file in your app folder

#File: app/start/artisan.php
Artisan::add(new YourCommandClass);

In Laravel 5, you have an App\Commands\Kernel class that manages your application configuration, and you register your commands by adding to the commands array

#File: app/Http/Kernel.php    
class Kernel extends ConsoleKernel {

    //...
    protected $commands = [
        'App\Console\Commands\Inspire',
    ];    
}

You’ll also notice Laravel now generates commands in the App\Console\Commands namespace. In Laravel 4.2 the App\Console\Commands\Inspire class would have been a global class named AppConsoleCommandsInspire, or something similar.

By dumping both the Illuminate and Composer classmap autoloaders, Laravel 5 solves many of the autoloader interaction problems we discussed last time.

Other Application Autoloading Changes

Let’s take another look at Laravel 5’s stock application autoloader sections in composer.json

#File: composer.json
"autoload": {
    "classmap": [
        "database"
    ],
    "psr-4": {
        "App\\": "app/"
    }
},
"autoload-dev": {
    "classmap": [
        "tests/TestCase.php"
    ]
},

There’s two other things to make note of. First, the database/ folder (now off the root project folder, and not in the app/ folder) is still parsed by Composer’s classmap autoloader, and migrations/seeds classes still live in the global PHP namespace. This means the potential for autoloading conflicts still exists, although with only the database folder under classmap autoloading the potential surface area for conflicts is greatly reduced.

The other thing to note is Laravel’s base TestCase class is still loaded via a classmap autoloader, but has been moved to the autoloader-dev branch

#File: composer.json
"autoload-dev": {
    "classmap": [
        "tests/TestCase.php"
    ]
},

Without getting too deeply into Composer’s “dev” and “no-dev” concepts, this move into autoload-dev ensures the TestCase class will not be included when you or Composer calls dumpautoload with the the --no-dev option

composer dumpautoload --no-dev

This should only come up when you’re planning your application deployment. The short version is Composer’s “no-dev” mode ensure packages are only downloaded dependencies they need to run, and will not download the additional packages a developer would need to add new code and features to the package.

Laravel Framework Autoloader Changes

Let’s take another look at the new framework composer.json autoload section

#File: vendor/laravel/framework/composer.json
"autoload": {
    "classmap": [
        "src/Illuminate/Queue/IlluminateQueueClosure.php"
    ],
    "files": [
        "src/Illuminate/Foundation/helpers.php",
        "src/Illuminate/Support/helpers.php"
    ],
    "psr-4": {
        "Illuminate\\": "src/Illuminate/"
    }
},

In addition to the psr-4 section, there’s still a classmap and files section. The classmap autoloader hasn’t changed since 4.2 — it’s still that weird global IlluminateQueueClosure class defined in a non-PSR compliant path at src/Illuminate/Queue/IlluminateQueueClosure.php.

The files autoloader is slightly different from Laravel 4.2, in that there’s now two files included. However, just as in the previous version, neither of these files defines any class autoloaders — instead, these files define a number of top level helper functions. Splitting the helpers into two files looks like an attempt to keep Laravel specific helper functions separated from generic helper function a programmer could use separate from Laravel.

Wrap Up

To an outside observer, the changes in Laravel’s autoloader may seem arbitrary and subject to the capricious whims of open source developers. However, after examining the autoloader implementation in detail, and understanding its shortcomings in Laravel 4, we can quickly understand why Laravel’s core developers made the changes.

This pattern applies to other changes in Laravel 5, as well as changes to any programming framework, language, or system. Knowing how to use your tools is always important, but understanding how your tools are built and how they fall short is one of the best ways to cope with an ever changing technology landscape.

Originally published February 20, 2015