PHP Namespaces

PHP Namespaces

PHP namespaces allow you to namespace your functions! Ok, so I know that’s circular reasoning. Let’s see what that means.

We’re all familiar with the way that files and folders work on our PCs. If you have two files with the same name, then they cannot exist in the same folder.

So, if I have a file called notes.txt with all my work related notes, then I can’t also have a file called notes.txt with all my personal related notes in the same folder. I could have a structure like this though:

tree view

 

PHP namespaces are a bit like that.

As an example, I have two classes from two separate authors and I need to use their functionality in my php file.

The classes are called class1.php and class2.php and my file is index.php. The problem is that both classes have a class name of “MyClass” and further more, both of those classes have a function called “TEST”.

 

// CLASS2.PHP

<?php
class MyClass
{
    function TEST()
    {
        print "This is TEST->class1<p>";
    }
}
?>
// CLASS2.PHP

<?php
class MyClass
{
    function TEST()
    {
        print "This is TEST->class1<p>";
    }
}
?>

My index.php file looks like this:

<?php

include("./class1.php");
include("./class2.php");

$obj1 = MyClass();
$obj2 = MyClass();

$obj1->TEST();
$obj2->TEST();

?>

When I run this code in a browser on a LAMP / MAMP / WAMP server, I get the following error:

Fatal error: Cannot declare class MyClass, because the name is already in use in /var/www/html/class2.php on line 3

This is a problem which PHP namespaces solves. We “wrap” each of our classes in a namespace. Typically namespaces might have the name of the vendor. Also, namespaces can have multiple levels but for now lets consider a single level.

If the class authors changed their code to look like this:

// CLASS1.PHP

<?php
namespace Delta
{
        class MyClass
        {
                function TEST()
                {
                        print "This is TEST->class1<p>";
                }
        }
}
?>

and

// CLASS2.PHP

<?php
namespace Acme
{
        class MyClass
        {
                function TEST()
                {
                        print "Hey y'all is TEST->class2<p>";
                }
        }
}
?>

then we could update our code to use the author’s namespaces to avoid conflicts. Here’ what our code would look like:

 

<?php

include("./class1.php");
include("./class2.php");

$obj1 = new Acme\MyClass(); // No leading slash.. could be a problem if you're not in the global namespace
$obj2 = new \Delta\MyClass();

$obj1->TEST();
$obj2->TEST();

?>

We now use the namespace as part of our variable declaration when creating the object. This produces the expected result with no errors.

Namespaces – Relative or absolute?

You may already be familiar with the way directories work. If I am in a certain directory then I can get to another directory either by browsing relative to the one I’m or absolutely.

To make this clear, consider our simple folder structure:

tree view

 

 

 

If I am in then “personal” folder and I want to get to the notes.txt file in the “work” folder, I can either get to it relative to where I am like so:

cat ../personal/notes.txt (which means go back one level from where I am, then enter personal).

OR I can get to it absolutely like this: cat /home/john/personal/notes.txt.

If I use the absolute path it doesn’t matter where I currently am, that will always work.

Namespaces are a little like folders in this respect too.

In our index.php code above I deliberately declared the object variable slightly differently:

$obj1 = new Acme\MyClass(); // No leading slash.. could be a problem if you’re not in the global namespace

$obj2 = new \Delta\MyClass();

For object one I used a relative namespace. That means, find Acme namespace relative to the one I’m in. It just so happens that we were in the global namespace so that all worked out ok. But if I was in, for example, MyNamespace then the first declaration would fail because it would actually be looking for the class in:

\MyNamespace\Acme\MyClass()…

To get around that its usually simpler to use absolute namespace “paths” by prepending a back slash like we did for obj2. That just says, “no matter where I am now, start looking for the Delta namespace from the global namespace.

Conclusion

Need more info? Have a question? Please comment below and I’ll try to answer as quickly as possible. For more info here are two great links:

https://daylerees.com/php-namespaces-explained/

https://mattstauffer.co/blog/a-brief-introduction-to-php-namespacing

Share

Leave a Reply

Your email address will not be published. Required fields are marked *