In my Beyond Frameworks talk, I explained how a component-based architecture can help answer some of the important (i.e. expensive!) questions you might face when creating long-lived apps that rely on a PHP framework. In this series of blog posts, I’m going to look at how to go about creating and working with components.

A component-based approach works well with the new namespace support added to PHP 5.3, and indeed I’m making full use of this in the components I’m building for this tutorial. But not everyone is ready to move to namespaces, and when you start to consume older components inside yours, you might run into errors.

Namespaces Recapped

The whole idea behind namespaces is to make life easier for developers, by doing away with having to type incredibly long class names all the time. For example, take the ConsoleDisplayLib component I recently released. In the pre-PHP 5.3 days, I would have had to define the classes it provides like this:

class Phix_Project_ConsoleDisplayLib_StdOut { ... }

… and then when I wanted to use it, I would have to do this:

$stdout = new Phix_Project_ConsoleDisplayLib_StdOut();

A workable system, to be sure, and one that OO PHP programmers have used for many years, but hardly RSI-friendly, I’m sure you agree. With namespaces, however, things change. The class is now defined like this:

class Phix_Project\ConsoleDisplayLib\StdOut { ... }

Note the use of ‘\’ instead of underscores. That’s PHP’s new namespace separator, and it tells PHP that the class StdOut lives inside the Phix_Project\ConsoleDisplayLib namespace, which in turn lives inside the Phix_Project namespace. Namespaces are just another kind of scope, like local scope vs global scope. Hold that thought, because it’s these new scopes that affect our attempts to mix in non-namespaced code.

If I’m writing code that is part of ConsoleDisplayLib, to create a new StdOut object, I now only need to do this:

namespace Phix_Project\ConsoleDisplayLib;

$stdout = new StdOut();

PHP automatically expands ‘StdOut’ to mean ‘Phix_Project\ConsoleDisplayLib\StdOut’, because I’ve used the namespace keyword to tell PHP that this code is part of Phix_Project\ConsoleDisplayLib.

And that is where the fun begins.

Adding HTTP_Request2 To RepustateApi

I’ve made the choice to reuse the existing PEAR component HTTP_Request2. The PEAR project doesn’t currently use namespaces; all classes defined by HTTP_Request2 exist in the global scope. So if I try to use HTTP_Request2 like this inside my Repustate API client:

namespace Gradwell\RepustateApi;

...

$httpClient = new HTTP_Request2($url, HTTP_Request2::METHOD_POST);

… PHP reports the fatal error: Class Gradwell\RepustateApi\HTTP_Request2 not found.

First time you see this, you might be wondering what is going on, and how to fix it. After all, the class is called HTTP_Request2. Why is PHP trying to load a class called Gradwell\RepustateApi\HTTP_Request2?

The answer is simple. By using the namespace keyword at the top of the file, I’ve told PHP to assume that all of the code in this file is part of the Gradwell\RepustateAPI scope. So, just like in my ConsoleDisplayLib example where PHP automatically expanded StdOut to be Phix_Project\ConsoleDisplayLib\StdOut, PHP is going to expand HTTP_Request2 to be Gradwell\RepustateApi\HTTP_Request2.

That isn’t what we want, but that’s PHP’s fault. We need to tell PHP that, in this case, we want it to load HTTP_Request2, and not Gradwell\RepustateApi\HTTP_Request2.

Load From The Global Namespace

Getting PHP to load code from the global namespace, instead of from your component’s namespace, is very easy … you’ve just got to remember to do it everywhere. Simply make sure you’ve put a ‘\’ at the start of any classnames that are part of the global namespace:

namespace Gradwell\RepustateApi;

...

$httpClient = new \HTTP_Request2($url, \HTTP_Request2::METHOD_POST);

Remember to do this, and you’ll have no trouble working with non-namespaced components inside your own components.

Comments are closed.