What's new in PHP 5.3 – Namespaces

PHP 5.3 included a couple of significant new features that are worth giving their own space to cover. These are “namespaces” and “late static bindings”. I’ll discuss late static bindings in the chapter on objects and classes, but in this video we’ll look at namespaces.

Something you will see fairly often in larger PHP applications is classes with names like: Doc_Event_Model_BuildHelper
This sort of name is common, and provides a couple handy features. For one, if it follows the typical convention, you know that within whatever directory classes are kept, there is probably a folder called ‘doc’ with a folder called ‘event’ with a folder called ‘model’ with a file called ‘BuildHelper.php’. And assuming it’s PHP 5 or later, then there is most likely an __autoload function that tells PHP which path to check when trying to load this class. The other useful trait is that it avoids naming collisions. In PHP, no 2 classes can have the same name (and neither can constants or functions).

The downside to this convention is that class names can get very long, and there isn’t a similar convention for constants or functions, which similarly can’t have more than one instance of the same name. As a result, large programs often won’t define functions or constants except as static methods or constants on these long-named classes. Namespaces give you an alternate way of relating the various parts of your code, and prevents naming collisions with unrelated components.

The most basic way to think about namespaces is to liken them to your file manager’s directory structure. If all of your files were in the same folder, then no 2 files could have the same name, and as you added files over time, the file names would need to get pretty long to avoid overwriting existing files. So instead, we can use directories to organize our files into smaller related groups. And when you need to refer to a file, you can use a relative path or an absolute path.

With namespaces, like directories, we arrange our code into related parts. When we refer to namespaced code, we also use absolute or relative names. To use the proper terminology, we refer to these names as either as ‘qualified’, ‘unqualified’, or ‘fully-qualified’.

For instance, in the namespace ‘Foo’, a call like ‘$a = new Bar()’ would actually attempt to create a new instance of ‘Foo\Bar’, meaning some class called “Bar” within the namespace “Foo”. And in this case, we would refer to “Bar” as an unqualified name, since it has no namespace qualifier preceding it.

On the other hand, a fully-qualified name is like an absolute path to a file in your directory. The system knows it’s fully-qualified because it begins with a “\” character. So, using the example above, we might write “$a = new \Foo\Bar()”. In both examples, PHP would interpret this as a call to create a new instance of the class “Bar” residing in the namespace “Foo”.

Another way to create a fully-qualified name is to use the special “namespace” keyword. In this context, it acts much like the “self” keyword for a class. We could change our code to “$a = new namespace\Bar()” and it would again do the same thing. The usefulness here is that you can write code that is totally agnostic about the actual namespace it resides in, so long as it does actually contain some class by the name of “Bar”.

A “qualified name” is analogous to a relative path to a file within a sub-folder. You can have sub-namespaces the same as you can have sub-folders. So, back to our previous example, suppose there was a sub-namespace within Foo called “AnotherFoo,” which also had a class called “Bar”. If we wanted to specify that we were using that class instead, we could write “$a = new AnotherFoo\Bar()”. Notice there’s no forward slash at the beginning of the class name. So, what we actually get, in terms of a fully-qualified name, would be \Foo\AnotherFoo\Bar.

PHP will convert unqualified and qualified names into fully-qualified names at compile time.

Now that we’ve explored terminology, let’s look at how we actually define our code within a namespace.

When you declare a namespace within a file, it must come at the very start of the file. The only exception PHP allows is a declare statement to identify the type of encoding for the file. Consider the following code:
<html>
<?php
namespace Joe {

}

this code throws a fatal error because of the line above the php tag.

However if this is how your file begins:
<?php
namespace Joe {

}

Then you’re fine.

When you declare a namespace, any files you include within that namespace will also be a part of it. If the file ‘mover.php’ contains the class ‘Mover’, then in the following code:

namespace Joe {
include(“mover.php”);

}

the fully-qualified name for the class Mover will actually be \Joe\Mover.

In the same way, if you include a file that also defines a namespace from within a namespace, then that included namespace is going to be a sub-namespace.

For instance, if the following lines begin a file included within the namespace declaration ‘A’

namespace B {

function do_something() {

}

}

then the fully-qualified call to that function would be \A\B\do_something().

To be really useful though, it would be nice to be able to avoid writing a number of separate ‘include’ calls, and simply use the power of PHP 5’s ‘__autoload’ capability. __autoload is a special global function that PHP calls when an unrecognized class is referred to, instead of simply throwing an error (a la PHP 4). This function attempts to include a file based on the name of the class, in hopes that the referenced class will be found there.

Creating a custom __autoload function will be discussed in a separate video, but one of the most wonderful things about PHP 5.3 is that most of us won’t need to write one – the default __autoload function included with SPL already understands namespaces.

To enable, just call ‘spl_autoload_register()’ without paramters. If you want to specify a certain directory containing your classes, use ‘set_include_path’ to ensure that the autoload function checks there. And you can make sure that php uses a specific extension, such as ‘.class.php’ by calling ‘spl_autoload_extensions()’. Check out this example:

set_include_path(get_include_path() . ‘/classes’);
spl_autoload_extensions(‘.class.php’);
spl_autoload_register();

Now, whenever the code tries calling a class that hasn’t been included yet, say ‘\Useful\Class\Test’, the code will look inside the folder ‘classes/Useful/Class’ for a file called ‘Test.class.php’. And if it finds it, and the file contains a definition for the class ‘Test’ within the namespace ‘\Useful\Class’, then the class will be used seamlessly, and no explicit include file will be necessary.

Now it’s true that you can write your own __autoload function to do the same exact thing, but the spl_autoload function, since it’s actually written in C and not PHP, is going to be slightly faster. My advice is, whenever possible, try to create your directory structure in such a way as to make use of this handy default behavior.

December 06 2009 10:34 pm | PHP tutorial scripts

Comments are closed.