PHP Namespaces Tutorial

PHP-Namespaces-Tutorial

If you come from the C sharp or Java World, namespaces are not a new idea to you. In PHP, it was only once PHP 5.3 was released that namespaces gained official support in the language. Namespaces are changing the way applications in PHP are written, and they are likely one of the most important additions to the language in recent times. In this episode, we’ll take a look at what namespaces are, why they benefit us, and how to use them. Let’s dig in!

What Problems Do Namespaces Solve?

As you began your PHP programming, you likely found that over time as your programs became larger, things started to become cluttered and hard to find. In addition to this, you may have started to add libraries from other developers. Adding more classes and method names to your project starts to become problematic without namespaces because if you have a class or method with the same name, your program will fail. This is called having collisons. With namespaces, we fix the problem of collisions in our codebase. Namespaces support PHP classes, functions, and constants.

PHP Namespace Example

Before namespaces, all PHP code just lived in a global namespace. We can place a piece of PHP code into a namespace by using the namespace command like so:


<?php
namespace Vegibit;

Any PHP code that comes after this line now lives in the Vegibit namespace. You can also define more than one namespace in the same PHP file like so:


<?php
namespace Google;

Class Search {

    public function query() {
        return 'Searching Google';
    }
}


namespace Bing;

Class Search {

    public function query() {
        return 'Searching Bing';
    }
}
?>

Truth be told, it’s probably a good idea to keep your namespace to one per PHP file. After all, you’re using namespaces to reduce collisions and confusion in the application, no need to complicate things. The above example does highlight nicely the benefit of namespaces however. Notice that both the Google and Bing namespace each have a class named search and a method named query? You can’t do that in the global namespace! Since we declared these classes and methods in different namespaces however, we can use each class and method to our hearts content, with no need to worry about running into collisions.

PHP Namespace Hierarchy

Most times you will see namespaces following the convention of matching a folder structure. By using a backslash character between folder names so to speak, you can define very precise naming conventions for where your libraries and PHP code lives. Maybe you have some code that deals with the Facebook API. You might declare code in that folder like so, namespace VegibitFacebook while your database code might be namespace VegibitDatabaseMySQL and common helper methods might use namespace VegibitCommonStringHelpers. It is very flexible.

How To Use Namespaced Code

So far we have only looked at how to define namespaces and place code within them. What about when we need to actually make use of that code? Let’s take a look at a namespace example to demonstrate. We’ll create a file named vegilib.php and define a constant, function, and class with the Applicationvegilib namespace. Check it out:

vegilib.php


<?php
// application library
namespace Applicationvegilib;

const MAXVALUE = 'Infinity';

function learning() {
	return 'Get your learn on';
}

class Organization {
	static function teamplayer() {
		return 'There is no I in team';
	}
}

To call this code, we can use PHP just like this:

application.php


<?php
require('vegilib.php');

echo ApplicationvegilibMAXVALUE . '<br>';
echo Applicationvegiliblearning() . '<br>';
echo ApplicationvegilibOrganization::teamplayer() . '<br>';

Results in:

Infinity
Get your learn on
There is no I in team

You’ll note that we had to use the full namespace path in order for this code to run successfully. This is what is referred to as a fully qualified namespace and includes the initial backslash. So what happens if we just put this application code inside the same namespace? Let’s see!

application.php (namespaced)


<?php
namespace Applicationvegilib;

require ('vegilib.php');

echo MAXVALUE . '<br>';
echo learning() . '<br>';
echo Organization::teamplayer() . '<br>'; 
Infinity
Get your learn on
There is no I in team

Awesome! Since we now have the application code living in the same namespace, you can see that instead of having to use the full path in our execution code, we can simply access our constant, function, and class method directly since we are in the same namespace.

Importing Namespaces

As we just saw, you can place your application code into the same namespace as your library, and this will give you direct access to the guts of that library without having to specify the fully qualified namespace. Let’s look at importing namespaces using the use and as keywords, it’s quite slick! We’ll break up our earlier example of the Google and Bing namespaces into separate class files for this example.

google.php

<?php
namespace Google;
 
Class Search {
 
    public function query() {
        return 'Searching Google';
    }
}

bing.php


<?php
namespace Bing;
 
Class Search {
 
    public function query() {
        return 'Searching Bing';
    }
}

If we update our application.php file to the following:

<?php
use Google as g;
use Bing as b;

require ('google.php');
require ('bing.php');

$searchengine = new gSearch;
echo $searchengine->query() . '<br>'; 

$searchengine = new bSearch;
echo $searchengine->query() . '<br>'; 

Results in

Searching Google
Searching Bing

We’ll now find that we can search Google and Bing using the same Class and Method names, just from another namespace. Make note of both use Google as g; and use Bing as b;. What this says is that we want to use each namespace as something else. So in the case of the Google namespace, we can instantiate an object like this $searchengine = new gSearch; and to instantiate an object in the Bing namespace we can do this $searchengine = new bSearch;

If we omit the lines:

use Google as g;
use Bing as b;

we can still use those classes and methods but we’ll now have to include the full namespace when trying to instantiate an object like this:

<?php

require ('google.php');
require ('bing.php');

$searchengine = new GoogleSearch;
echo $searchengine->query() . '<br>'; 

$searchengine = new BingSearch;
echo $searchengine->query() . '<br>'; 
Searching Google
Searching Bing

Some of this is a matter of preference, while some of this is quite nuanced to the point of if you don’t follow the conventions very specifically, your app will break. When in doubt, hit up the official docs and various definitions and rules to be sure you are following the best practices.

What is __NAMESPACE__ ?

This is a constant that refers to the current namespace. In the global namespace, this constant has no value, or an empty string. Let’s adjust our most recent application code to test this out:

<?php
namespace Bing;
use Google as g;

require ('google.php');
require ('bing.php');

$searchengine = new gSearch;
echo $searchengine->query() . '<br>'; 

echo __NAMESPACE__;

Now what we have here is a snippet of PHP code that lives in the Bing namespace. Within this namespace we import the Google namespace and alias it as the letter g. Therefore, the object creation and method call runs, and we search google. Be echoing out the __NAMESPACE__ constant, we can see that yes, this file does live in the Bing namespace.

Searching Google
Bing

So what is this good for? A good question indeed! It turns out you can use this constant for debugging purposes as well as to create dynamically generated fully qualified class names.

Namespaces and Autoloading

Namespaces are going to be key for you to use autoloading in your PHP projects moving forward. Like we mentioned in this Composer Autoload Tutorial, Composer makes heavy use of Namespaces in order for it to work it’s magic. By learning your Namespaces as well as your psr-0 and psr-4 standards, you will be well equipped to deal with the new methods of PHP workflow.

Thank you for reading PHP Namespaces TutorialPlease do share using the buttons below!