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

Laravel Autoloader Interactions

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.

Pop quiz hotshot! You’ve put in a long day of programming. Your data models are complete, the prototype UI is done. You’re going to end the day creating a simple Laravel command. You run command:make

$ php artisan command:make PulsestormSomeCommand

You register your command

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

and then run artisan list to make sure it’s registered

$ php artisan list
{"error":{  "type":"ErrorException",
            "message":"Argument 1 passed to
            Illuminate\\Console\\Application::add() must be an 
            instance of Symfony\\Component\\Console\\Command\\Command,
            instance of PulsestormSomeCommand given, called in
            ...src\/Illuminate\/Support\/Facades\/Facade.php on line 208 
            and defined",
            //...

What do you do?

Bad Dennis Hopper impersonation aside, this is a real thing that’s happened to me twice. The first time it was tremendously confounding and I ended up wasting a few hours solving the problem. The second time I managed to remember the root cause relatively quickly, but it was still a bizarre wtf moment, and it’s what led to this Laravel/Composer autoloader series.

Today we’re going to talk about how Laravel’s autoloaders interact with each other when they’re loading the basic Laravel MVC class types. We’ll start with a definition of those MVC types, then move on to discussing how each type is loaded. Then, we’ll wrap up with a few examples of how Laravel 4.2’s autoloader introduces ambiguities that can be hard to figure out if you’re new to the platform — including an answer for the scenario above.

As a reminder, this series covers the specifics of Laravel 4.2 — but the concepts should be applicable across versions.

Laravel’s MVC Types

Types, or type systems, are another area where 50+ years of computer science and business practices have led to an overloading of terms. A “type system” might refer to the native types available in your language. For example, PHP has integers, floats, arrays, objects, strings, etc. A type system might also refer to the classes and objects you yourself have built for dealing with a particular problem domain (Vehicle, Car, Pontiac, etc). Languages like ruby, where everything is an object, can be particularly confusing on this issue, as ruby only has one type (an object), but the ruby standard library has classes which allow you to create an integer object, string object, etc.

All in all, when a developer says “type system” what they mean will be heavily influenced by the system they’re working in, and what it means to their day to day working and thinking.

When we say MVC types, we’re referring to the high level objects, classes, and methodologies Laravel provides for developers building web applications. Laravel itself has an immeasurable number of types under the hood — there’s Manager classes, Driver classes, etc. Understanding those types is important, but we’re not interested in those today. The “MVC types” we’re going to talk about are the types you’ll use most if you’re building Laravel applications.

The Types

The six Laravel types we’re interested in are

  • Controllers
  • Models
  • Artisan Commands
  • Database Migrations
  • Database Seeds
  • Test Cases

Controllers

Controllers are the C in MVC, and contain a entry point for any URL into your application. Laravel’s routing system is a little different than other MVC applications — your routes are setup with PHP callbacks in app/routes.php, and often won’t include any controllers. However, for larger applications with many entry points it makes sense to start categorizing request types with controller classes.

You can find Laravel 4.2 controllers in the app/controllers folder.

Models

Models are the M in MVC. There’s two schools of thought on models — some people think they’re the classes that interact with your database/datastore — other people think they’re the classes that contain the “business or domain logic” for your application. Laravel has a folder for model classes, and provides the Eloquent ORM for talking to the database.

You can find Laravel 4.2 models in the app/models folder

Artisan Commands

Laravel 4.2 ships with a system for creating command line programs. This system is named artisan, and is based on the popular Symfony Console component. By creating your command line scripts and programs with artisan, you don’t need to worry about code for parsing arguments, creating help files, etc., and you also improve discoverability of these commands for third parties using your program.

You can find Laravel 4.2 command classes in the app/commands folder, and you’ll (typically) register commands in the app/start/artisan.php file

Database Migrations

Laravel’s database migration system allows you to define a set of programmatic rules for modifying a database’s schema (adding tables, columns, etc.), and undoing those changes (“rolling back”). Migrations are critical for teams with multiple members, and also provide the ability to easily reinstall/rebuild the application on a different set of servers.

You can find Laravel 4.2 migration classes in the app/database/migrations folder.

Database Seeds

If Database migrations are for managing a database schema — seeds are for managing the default data inside a database. Some developers scoff at the idea of requiring your application to have a certain set of data available in the database to function, but other developers do not. A seed object contains code for “seeding” a database with default data.

You can find Laravel 4.2 database seed classes in the app/database/seeds folder.

Test Cases

While Laravel doesn’t have its own test system, A default Laravel 4.2 project does come configured to run phpunit test cases inside a Laravel bootstrapped environment.

You can find Laravel 4.2’s phpunit tests in the app/tests folder.

Autoloading Laravel’s Six MVC Types

Now that we have basic definitions for Laravel’s six MVC types, we’re going to discuss how Laravel’s autoloader chain interacts with each of these types.

First up are controllers. In Laravel 4.2 you set up a controller with something like the following in your routes.php file

Route::get('some-path/{id}', 'MySpecialController@showProfile');

and then define you controller in the following file

#File: app/controllers/MySpecialController.php
class MySpecialController extends BaseController
{
    public function showProfile($id)
    {
    }
}

Laravel will automatically instantiate the controller for you. Laravel does nothing special to include or require the controller definition file. That is, it relies on the autoloader to automatically load the controller file for you.

As to which autoloader Laravel uses to load a controller class — that’s a trickier question. Since this is a Laravel MVC type, you might assume that it’s the Laravel autoloader that handles this. This is buoyed by the fact that Laravel’s app/start/global.php file includes the controller path as one to autoload from

#File: app/start/global.php
ClassLoader::addDirectories(array(
    //...
    app_path().'/controllers',
    //...    
));    

However, Laravel’s main autoloader is last on the autoloader stack

  1. Illuminate\Foundation\AliasLoader::load
  2. Composer\Autoload\ClassLoader::loadClass
  3. Swift::autoload
  4. Illuminate\Support\ClassLoader::load

This means the Composer autoloader (listed second) gets first crack at autoloading the controller class. If you take a look at a stock composer.json in a Laravel 4.2 project, you’ll see something like this

//..
"classmap": [
    "app/commands",
    "app/controllers",
    "app/models",
    "app/database/migrations",
    "app/database/seeds",
    "app/tests/TestCase.php"
]
//..

That is, Laravel 4.2 ships using the classmap autoloader we discussed in our Composer Autoloader Features articles, and the classmap autoloader is configured to scan the app/controllers folder. If you have a Laravel project, try opening up the generated class map file at vendor/composer/autoload_classmap.php, and I bet you’ll find your controller file(s) listed there.

So, this means we can say, definitively, that Laravel uses the Composer autoloader to load controller classes, right?

Wrong.

Consider the following use case — add the following to your app/routes.php file

Route::get('testbed', 'PulsestormTestbedController@test');

and then create a controller file at

#File: app/controllers/PulsestormTestbedController.php
<?php    class PulsestormTestbedController extends BaseController
{
    public function test()
    {
        var_dump("I am loaded");
    }
}

and load your URL.

http://laravel.example.com/index.php/testbed

You should see the text I am loaded dumped to the browser.

That is, Laravel successfully loaded your controller class and instantiated an object — except that shouldn’t be possible. Since we never ran composer dumpautoloader, the Composer autoloader doesn’t know about the new controller file.

Remember though, Laravel has four autoloaders

  1. Illuminate\Foundation\AliasLoader::load
  2. Composer\Autoload\ClassLoader::loadClass
  3. Swift::autoload
  4. Illuminate\Support\ClassLoader::load

After running Illuminate\Foundation\AliasLoader::load, Composer\Autoload\ClassLoader::loadCLass, and Swift::autoload, Laravel finally runs its own, internal autoloader, Illuminate\Support\ClassLoader::load. This autoloader actually loads the controller class.

So, to sum up how and where Laravel autoloads a controller class

A stock Laravel 4.2 system will use Composer classmap autoloader to load a controller’s class name. If the classmap autoloader fails to load a class, Laravel will fallback to using its own Illuminate\Support\ClassLoader::load autoloader.

This is, in my opinion, a bit of sloppy systems engineering. It introduces ambiguity as to which method will load a controller class/object — it also creates a situation where Laravel has a defined naming convention for its controller in Illuminate\Support\ClassLoader::load, but has no naming convention for controllers loaded via the classmap autoloader, (remember, Composer’s classmap generator will run through every .php and .hh file in a directory looking for classes to add).

Laravel follows a similar pattern when loading a model class. That is, a stock Laravel composer.json file ships with the app/models folder included in the classmap section

"classmap": [
    //...
    "app/models",
    //...    ]

This means the classmap autoloader will handle every .php or .hh file in app/models. However, this same “we haven’t run dumpautoload yet” rules apply. If the classmap autoloader fails to load a Model class, Laravel will fall back to Illuminate\Support\ClassLoader::load autoloader.

While I may consider this sloppy systems engineering, I can easily see a case being made that it’s good product engineering. I’m not familiar enough with the history to say for sure, but I can imagine the Laravel core team wanting to add some sort of Composer autoloader support to be in line with current PHP standards, but not wanting to remove the traditional Laravel autoloader if existing users were still using it. Backwards compatibility may be a dirty word to some, but these sort of compromises are the heart of product engineering, and impossible to judge without the context of the original development cycle.

As we’ll see below though, this classmap vs. Laravel autoloader problem can create real problems for developers who stumble into it.

Generated Code

Next, we’re going to talk about autoloading artisan command classes, database migrations, and database seed classes.

The first thing to know — the “Composer first, then Illuminate” situation we described above applies to database seed classes, and artisan commands. Again, if we look at composer.json

"classmap": [
    "app/commands",
    //...
    "app/database/seeds",
    //...
]

We see both the app/commands folder and app/database/seeds folders are part of the Composer classmap autoloader. If we then look at the default folders the Illuminate autoloader will look through

ClassLoader::addDirectories(array(

    app_path().'/commands',
    //...
    app_path().'/database/seeds',
    //...
));

We see both the app/commands folder and app/database/seeds folder.

Confusingly though, the Composer classmap/Illuminate loader fallback does not apply to database migrations. Autoloading Laravel’s migrations is handled strictly by the classmap autoloader — you won’t find the migrations folders added to the Illuminate ClassLoader. This is most likely due to the special naming of migration files (YYYY_MM_DD_name.php), which means the Illuminate autoloader has no chance of loading these class files.

There’s another wrinkle to commands and migrations (but not seeds), and that’s how a working Laravel developer creates them. While you’ll typically create models and controllers by hand, when it comes to migrations, seeds, and commands you’ll be using code generation.

That is, when you want to add a migration, you use artisan’s migrate:make command

$ php artisan migrate:make add_some_table_to_database
Created Migration: 2015_02_06_164452_add_some_table_to_database
Generating optimized class loader

Notice the second line of output (Generating optimized class loader). Behind the scenes artisan is running composer dumpautoloader for you, and this regenerates the classmap autoloader files. i.e., your migration class file in 2015_02_06_164452_add_some_table_to_database.php is ready to be autoloaded.

There’s also a command for generating new artisan commands

$ php artisan command:make MyCommandClassName
Command created successfully.

Curiously, despite knowing about the new class, Laravel doesn’t automatically run composer dumpautoload for you in this situation — perhaps because the core artisan developers know the Illuminate class loader will take care of this.

Test Cases

The last Laravel MVC type we’ll talk about are your test classes. Tests are a little different, because they don’t run in a pure Laravel bootstrapped environment. Instead, tests run in a phpunit bootstrap environment, and this phpunit environment bootstraps a Laravel environment.

This may seem a pedantic distinction — but it has important consequences. For example, your test classes in app/tests? Laravel does not autoload these. In fact, your test classes aren’t autoloaded at all. PHPUnit manually includes these files (for reasons both historic and practical). If you’re curious where this happens in PHPUnit’s systems code, take a look at this method

#File: vendor/phpunit/phpunit/src/Util/Fileloader.php
public static function load($filename)
{
    $oldVariableNames = array_keys(get_defined_vars());

    include_once $filename;

    $newVariables     = get_defined_vars();
    $newVariableNames = array_diff(
        array_keys($newVariables), $oldVariableNames
    );

    foreach ($newVariableNames as $variableName) {
        if ($variableName != 'oldVariableNames') {
            $GLOBALS[$variableName] = $newVariables[$variableName];
        }
    }

    return $filename;
}

So why are we mentioning test classes if there’s no autoloader? While PHPUnit autoloads individual test classes, it does not load any base test classes you may have. Laravel itself ships with a base test class named TestCase

#File: app/tests/TestCase.php     
class TestCase extends Illuminate\Foundation\Testing\TestCase {

    /**
     * Creates the application.
     *
     * @return \Symfony\Component\HttpKernel\HttpKernelInterface
     */
    public function createApplication()
    {
        $unitTesting = true;

        $testEnvironment = 'testing';

        return require __DIR__.'/../../bootstrap/start.php';
    }

}

It’s this base test case that bootstraps the Laravel testing environment.

So, if PHPUnit doesn’t load this class, what does? Take one last gander at Laravel’s stock composer.json

"classmap": [
    //...
    "app/tests/TestCase.php"
]

Here Laravel has explicitly added this base test case to the classmap autoloader.

If you wanted to create your own base tests classes, you’d do the same. That is, you’d add the file to composer.json

"classmap": [
    //...
    "app/tests/MyBaseTestCase.php"
]

And then run the dumpautoload command

$ composer dumpautoload

Swift Autoloader

There’s one last class type to talk about, and it’s not a Laravel MVC class — it’s any class that’s a part of the Swift Mailer library.

#File: vendor/swiftmailer/swiftmailer/lib/classes/Swift.php    
public static function autoload($class)
{
    // Don't interfere with other autoloaders
    if (0 !== strpos($class, 'Swift_')) {
        return;
    }

    $path = dirname(__FILE__).'/'.str_replace('_', '/', $class).'.php';

    if (!file_exists($path)) {
        return;
    }

    require $path;

    //...
}

There’s a small chance this legacy autoloader might cause class name conflicts in your program. For example, try running the following code in a Laravel bootstrapped environment (i.e. a Laravel Route callback or controller action)

$object = new Swift_Message;
$r      = new ReflectionObject($object);
var_dump($r->getFilename());

This bit of code creates a Swift_Message object, and then uses PHP’s reflection class to find the class definition. In a working system, it will var_dump the following file path.

string '/path/to/laravel/login/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Message.php' 

Now, crete the following class file

#File: app/models/Swift_Message.php
<?php    class Swift_Message
{
}

and run the Composer dumpautoload command

$ composer dumpautoload

If you re-run the reflection code above, you’ll see the following

string '/path/to/laravel/app/models/Swift_Message.php' 

That is, PHP is now loading the class we created instead of the native SwiftMailer Swift_Message class. This happens because of the autoloader stack order

  1. Illuminate\Foundation\AliasLoader::load
  2. Composer\Autoload\ClassLoader::loadClass
  3. Swift::autoload
  4. Illuminate\Support\ClassLoader::load

The Composer\Autoload\ClassLoader::loadClass autoloader wins out over Swift::autoload because PHP calls Composer\Autoload\ClassLoader::loadClass first.

Now, it’s unlikely you’ll run into this problem yourself, you’d need to be naming your classes with a Swift prefix and not following the standard naming conventions for model classes. However, it is theoretically possible, and something you’ll want to watch out for.

Framework vs. Application

Another area you’ll want to be careful with is conflicts between your application classes and framework classes.

For example, in PHP, there’s nothing to stop you from defining a class in Laravel’s Illuminate namespace.

#File: app/models/Illuminate/View/Test.php
<?php    namespace Illuminate\View;
class Test
{
}

With the above in place, give the following reflection snippet a try

$reflection = new ReflectionClass('Illuminate\View\Test');
var_dump($reflection->getFilename());

PHP will print out the path to the class, letting us know we’ve correctly defined it.

string '/path/to/laravel/app/models/Illuminate/View/Test.php' (length=88)

Next, we’re going to create a Illuminate\View\View class

#File: app/models/Illuminate/View/Test.php
<?php    namespace Illuminate\View;
class View
{
}

If we run this one through our reflection snippet

$reflection = new ReflectionClass('Illuminate\View\View');
var_dump($reflection->getFilename());    

we’ll see that PHP does not return a path to our class — instead, it returns the path to the real Illuminate\View\View class in the Laravel framework library.

string '/path/to/login/vendor/laravel/framework/src/Illuminate/View/View.php' (length=106)

So far so good — this is reasonable behavior to expect from a framework. However, without adding any extra code, run the dumpautoload command,

$ composer dumpautoload

and try running the reflection snippet again

string '/path/to/app/models/Illuminate/View/View.php' (length=88)

This time PHP returns the path to the Illuminate\View\View class we defined. That’s because the Composer classmap autoloader wins out over the PSR-0 autoloader defined in the framework composer.json

Other PHP frameworks promote this sort of behavior as a way to selectively replace core system/framework classes — if you’re a Magento developer you’re probably familiar with code pool overrides. While you may be tempted to take advantage of this behavior for a quick fix to an application you don’t understand, without an implicit promise from the framework developer to maintain this behavior, I’d treat this as a side effect to be wary of rather than a feature to rely on.

The Answer to this Week’s Puzzler

So, with all tha said, have you figured out the pop quiz question we led off with?

The answer is, in part, pilot error. What I left out was that, immediately prior to running command:make, I had absentmindedly run the following

$ php artisan migrate:make PulsestormSomeCommand
Created Migration: 2015_02_08_153827_PulsestormSomeCommand
Generating optimized class loader

Now, this was obviously a dumb thing to do — but what this did was create a PulsestormSomeCommand class in the migrations folder.

#File: app/database/migrations/2015_02_08_153827_PulsestormSomeCommand.php 
//...
class PulsestormSomeCommand extends Migration {
    //...    
}

Then, when I realized I’d accidentally run the wrong command, I ran the correct one

$ php artisan command:make PulsestormSomeCommand
Command created successfully.

And Laravel created a command class in the app/commands folder

#File: app/commands/PulsestormSomeCommand.php
//...    
class PulsestormSomeCommand extends Command {
    //...    
}

So, what I had now was a system with two classes named PulsestormSomeCommand in the global namespace. Laravel itself still served pages fine — because Laravel loads neither the command or migration classes during normal system execution.

However, when I tried to run php artisan, PHP ended up instantiating the PulsestormSomeCommand migration class. With that context, the error message

Argument 1 passed to Illuminate\Console\Application::add() must be an instance of Symfony\Component\Console\Command\Command, instance of PulsestormSomeCommand given, called in

makes a lot more sense. Laravel’s telling us it can’t use our migration class as a command class.

Transitionary Period

This brings us, at long last, to the end of Laravel’s autoloader architecture. Beyond the utility of being able to debug autoload related bugs and day-to-day blocking issues, Laravel’s autoloader offers an interesting perspective on the the tradeoffs of systems engineering vs. product engineering.

The autoloader architecture in Laravel 4.2, while solid, does show signs of being in transition. Next time we’ll tie a bow on our series with a look at the changes to this architecture in the recently released Laravel 5.

Originally published February 15, 2015