How did YOU implement namespaces?

There’s been some talk in our development team about altering our applications to utilize namespaces. This wasn’t something we could consider until all of our production servers were running 5.3, but now they are so we can begin considering this change. I think the most intriguing aspect is how namespaces can impact your file structure. So I’m curious for those of you that utilize namespace how did it effect how you store files in your applications? What lessons have you learned, what tips can you share?

On my side, we’ve tossed around the idea of holding interfaces, abstract definitions , filters etc in separate folders. For instance our file structure may change to something more like
system/controllers/
system/abstracts/
system/interfaces/

Where a sample class from the controllers directory may look like:

SampleController.php


namespace system\\controllers

class SampleController extends \\system\\abstracts\\Controller implements \\system\\interfaces\\Controller
{
     // Class definition
}

Obviously each file in each directory would declare itself a part of it’s appropriate namespace. For instance all class held in the ‘interfaces’ directory would declare themselves with namespace ‘system\interfaces’. Obviously this would allow us to use an autoloading that would work similar to this:


function __autoload( $class_name ) {
	require_once( str_replace( '\\\\' , DIRECTORY_SEPARATOR , $class_name ) . '.php' );	
}

We’re still bouncing this one around but I’d love it if anyone here could add some input, advice or general tips learned from your own implementations if namespaces. We use an internally developed MVC so this might be an opportunity for us to really make some deep changes.

What you have presented there is generally the way I have seen it done. Not only in terms of PHP frameworks but others as well. Though I would recommend adding the a way to achieve a custom mapping where the name is not directly mapped to the folder structure.

Thanks for the replay oddz, could you elaborate on this plz? Or point me to an example?

PNL (working title of my framework) uses a namespace extension of ns on the directories. Class PNL/PDF/Document will be in a filepath like /classes/…/PDF.ns/…/Document.php. Folders without a namespace extension are ignored and exist only for programmer organizational convenience. The only limitation is that namespaced classes must be a child of a namespace folder as in the example above. The interceding folders aren’t relevant to the system. At startup a search routine is used against the classes folder of the system root (the PNL namespace) and the active project folder (namespace and path set in configuration). The computer builds a map of namespaces and classes to filepaths. Then, in production mode, this is memcached using APC as globing the file system on each script run to find all the classes is wasteful.

By default the system only scans two folders recursively for classes and namespaces, but the config file can be set to force the system to consider as many top folders as you’d like (classes is one such folder, by recursively scanning I mean to say it scans classes and the contents of all its folders and all those folders contents, recursively). Another design limitation is php filename must match class name, and every php file encountered is presumed to be a class file except one - definitions.php.

The definitions.php holds the definitions of the namespace functions and constants that are not members of classes. If a namespace has any such functions and constants they are expected to be found directly within the .ns directory, so the definitions of namespace A will be in “A.ns/definitions.php” This approach works smoothly enough provided you never try to reference a namespace function or constant without first trying to reference (and thereby loading) a class in the same namespace. The inability to directly autoload constants and functions is a weakness of the PHP language. This is a work around, but not an airtight one.

P.S. Do not use the magic __autoload function. Use the standard PHP library autoload functions instead to register your autoloaders.

Consider taking a look at the Symfony2 framework manual especially:

Symfony 2 is a recently released, redesgned from the ground up framework based on namespaces.
Lots of good stuff to look through and steal especially their universal class loader.

By the way, your example should probably be something like:


namespace system\\controllers

use system\\abstracts\\Controller as AbstractController;
use system\\interfaces\\Controller as InterfaceController;

class SampleController extends AbstractController implements InterfaceController
{
     // Class definition
}  

Does the same thing but a bit easier to read.