PHP Namespaces and Autoloaders, Reviewed

Several years ago, I wrote an article about this, and it was really a mess, but the PHP community understanding about autoloaders and namespaces was a lot worse than it is today. This article attempts to amend and supercede the original, and explain the magic.

If you have any old PHP programs lying around, or you still write old-style PHP code, you have seen this at the top of some pages:

[code]
require_once("lib/db.inc.php");
require_once("lib/functions.php");
require_once("lib/classes/Response.class.php");
[/code]

There were disparate libraries being brought in, and some of them provided classes.

Today, contemporary code looks more like this:

[code]
namespace App\Controller;

use Symfony\Component\HttpFoundation\Response;
[/code]

The use directive bring in a single class, which is in a single file, stored in …some/path/to/Symfony/Component/HttpFoundation/Response.php.

Somehow, PHP brought together the old system and the new system, and they co-exist.

PHP Namespaces

PHP namespaces were introduced with PHP 5.3, back in 2009.

As the number of classes proliferated, there were the inevitable name clashes. Which Database class was it? Which Db class was it?

The fix was naming conventions. A project would prepend a string to the name: CI_Database, S_Database, ST_Database.

You also had a ton of global variables. The fix? Put them into classes, or static classes, and they are all inside a class’ namespace.

Why do we need the “namespace” keyword?

If you think of what a PHP program is, with all those “includes”, it’s like a very, very long concatenated script. The semantics of “include” were weird..

The namespace keyword allows us to say, from within this long concatenated script, “from now on, we are in a different namespace”.

From that point on (until the next namespace), the function and class declarations are no longer global. However, variable declarations are still global.

Example:
[code]
namespace Com;

$x = 1; // is still $x
$y = 2; // is still $y

class Database {
} // is really Com\Database

$z = new Database(); // is really $z = new Com\Database();
$z->something(); // is really $z->something();
[/code]

Of course, it means all the things have longer names. That’s OK, because you can “use” the class. More on this later.