PHP: Basic Introduction to Namespaces


 
 

History of PHP Namespaces

In PHP prior to 5.3 (2009), any class you define lived at the same global level as other classes.

Class User, class Contact, class Db they're all together in the global namespace.

This may seem simple, but it makes organization tough, which is why PHP developers started using underscores to separate their class names. For example, if I were developing a package called "Cacher", I might name the class Manoweb_Cacher so as to differentiate it from someone else's Cacher--or Manoweb_Database_Cacher, to differentiate it from an API cacher.

That worked decently, and there were even autoloading standards that separated out the underscores in class names for folders on the file system; for example, Manoweb_Database_Cacher would be assumed to live in the file Manoweb/Database/Cacher.php.

An autoloader is a piece of code that makes it so that, instead of having to require or include all of the files that contain your class definitions, PHP knows where to find your class definitions based on a particular convention.

But it was pretty messy, and often ended up with class names like Zend_Db_Statement_Oracle_Exception and worse. Thankfully, in PHP 5.3, real namespaces were introduced.

The basics of namespaces

Namespaces are like a virtual directory structure for your classes. So class Manoweb_Database_Cacher could become class Cacher in the Manoweb\Database namespace:

<?php 

class Manoweb_Database_Cacher {}

is now:

<?php 

namespace Manoweb\Database;

class Cacher {}

And we would refer to it elsewhere in the app as Manoweb\Database\Cacher.

A real example with namespaces

Let's take Upbooking--it's a Reservation System with a financial component, so it tracks Customers and receipts, among many other things.

Let's set Upbooking as our top-level namespace (sort of like the parent folder--usually named after your app or package). This might have some classes related to Contacts, and some related to Billing, so we're going to create a sub-namespace for each, Upbooking\Billing and Upbooking\Contacts.

Let's make a class or two in each:

<?php 

namespace Upbooking\Billing;

class Receipt {}
<?php 

namespace Upbooking\Billing;

class Subscription{}
<?php 

namespace Upbooking\Contacts;

class Customer {}

So, we're picturing a directory structure like this:

Upbooking
    Billing
        Receipt
        Subscription
    Contacts
        Customer

Referencing other classes in the same namespace

So, if a Subscription can send a Receipt, it's easy to refer to it:

<?php 

namespace Upbooking\Billing;

class Subscription
{
    public function sendReceipt()
    {
        $receipt = new Receipt;
    }
}

Since Receipt is in the same namespace as Subscription, you can just refer to it like you would if you weren't using namespaces.

Referencing other classes in different namespaces

OK, but what if I want to reference a Receipt inside of a Customer?

<?php 

namespace Upbooking\Contacts;

class Customer
{
    public function sendReceipt()
    {
        // This won't work!
        $receipt = new Receipt;
    }
}

You guessed it: This won't work.

We're in the Upbooking\Contacts namespace, so when we wrote new Receipt, PHP assumes we're talking about Upbooking\Contacts\Receipt. But that class doesn't exist, and that's not what we're looking for.

So, you'll get a Class Upbooking\Contacts\Receipt not found error.

You might be tempted to modify it to instead say $receipt = new Upbooking\Billing\Receipt--but even that won't work. Since we're in the Upbooking\Contacts namespace right now, it's seeing anything you write as being relative to the namespace you're in. So that would try to load a class named Upbooking\Contacts\Upbooking\Billing\Receipt, which also clearly doesn't exist.

Use blocks and Fully-Qualified Class Names

Instead, you have two options:

First, you can precede it with a slash to create its FQCN (Fully Qualified Class Name): $receipt = new \Upbooking\Billing\Receipt;, which sends the signal to PHP to escape out of the current namespace before looking for this class.

If you precede the full namespace with a slash, creating the FQCN, you can refer to this class anywhere in your app without worrying about your current namespace.

Or, Second, you can use the class at the top of the file, and then just reference it as Receipt:

<?php 

namespace Upbooking\Contacts;

use Upbooking\Billing\Receipt;

class Customer
{
    public function sendReceipt()
    {
        $receipt = new Receipt;
    }
}

As you can tell, use imports a class from a different namespace into this namespace so we can refer to it more easily. Once you've imported the class, any time you reference Receipt in this class, it'll assume you're pointing to the imported class.

Aliasing

But, what if your class needs access to both Upbooking\Contacts\Receipt and Upbooking\Billing\Receipt? What if you also have a Receipt class in your current namespace?

You can't just import the Upbooking\Billing\Receipt class, or you won't be able to use both--they'd both have the same name in this class.

Instead, you'll need to alias it. You can change the use statement to something like use Upbooking\Billing\Receipt as BillingReceipt;. Now you've aliased the class, and then you can refer to the imported class as BillingReceipt throughout your class.

PSR-0/PSR-4 Autoloading

You know the folder analogy I just used above?

It's easy to think about your classes that way, but there's actually not any inherent connection between your namespaces and your files' structure. Unless you use an autoloader, PHP doesn't have any idea where those classes actually live in your directory structure.

Thankfully, PSR-0 (now deprecated) and PSR-4 are autoloading standards that actually map your namespaces to real folders. So, if you're using PSR-0 or PSR-4--which is extremely likely if you're using Composer or any modern framework-- and a compatible autoloader, you can assume that the classes actually are in folders.

Composer and PSR-4 Autoloading

So, let's say I want the Upbooking namespace to live in my src folder.

Here's my folder structure for a generic, framework-independent project:

app
public
src
    Billing
    Contacts
vendor

As you can see, the src folder represents the Upbooking top level namespace. Since I'm using Composer as my autoloader, all I need to do to get my application to autoload my classes is teach Composer how to map namespaces to folders. Let's do that using PSR-4.

I'm going to open up composer.json and add a PSR-4 autoload section:

{
    "autoload": {
        "psr-4": {
            "Upbooking\\": "src/"}
    }
}

So you can see: the left side is the namespace that we're defining (note that you need to escape the slash separators here by doubling them), and the right side is the directory.

As you can see, there's a lot going on here, but it's really pretty simple: 98% of the time, you're going to be working with a PSR-4-structured, Composer-autoloaded, set of classes.

So 98% of the time, you can check your composer.json, figure out where the root of the top level namespace lives, and assume you'll then have a one-to-one map of your namespace and the folders/files in that directory. Done.

And remember: next time you get Class SOMETHING not found, you probably just need to remember to import it with a use statement at the top of your file.

 
 

tags: php namespaces


We use our own cookies and third-party cookies to improve our services, show products based on your preferences, analyse the browsing habits of our users, and enable interaction with social networks. Continuing to browse our sites implies full acceptance of their use. You can change your cookie setting or get more information here: Cookies policy .