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.
Janeth Kent
Licenciada en Bellas Artes y programadora por pasión. Cuando tengo un rato retoco fotos, edito vídeos y diseño cosas. El resto del tiempo escribo en MA-NO WEB DESIGN AND DEVELOPMENT.
Related Posts
Examine the 10 key PHP functions I use frequently
PHP never ceases to surprise me with its built-in capabilities. These are a few of the functions I find most fascinating. 1. Levenshtein This function uses the Levenshtein algorithm to calculate the…
How to Track Flight Status in real-time using the Flight Tracker API
The Flight Tracker API provides developers with the ability to access real-time flight status, which is extremely useful for integrating historical tracking or live queries of air traffic into your…
What is a JWT token and how does it work?
JWT tokens are a standard used to create application access tokens, enabling user authentication in web applications. Specifically, it follows the RFC 7519 standard. What is a JWT token A JWT token…
PHP - The Singleton Pattern
The Singleton Pattern is one of the GoF (Gang of Four) Patterns. This particular pattern provides a method for limiting the number of instances of an object to just one.…
How to Send Email from an HTML Contact Form
In today’s article we will write about how to make a working form that upon hitting that submit button will be functional and send the email (to you as a…
The State of PHP 8: new features and changes
PHP 8.0 has been released last November 26: let's discover together the main innovations that the new version introduces in this language. PHP is one of the most popular programming languages…
HTTP Cookies: how they work and how to use them
Today we are going to write about the way to store data in a browser, why websites use cookies and how they work in detail. Continue reading to find out how…
The most popular Array Sorting Algorithms In PHP
There are many ways to sort an array in PHP, the easiest being to use the sort() function built into PHP. This sort function is quick but has it's limitations,…
MySQL 8.0 is now fully supported in PHP 7.4
MySQL and PHP is a love story that started long time ago. However the love story with MySQL 8.0 was a bit slower to start… but don’t worry it rules…
A roadmap to becoming a web developer in 2019
There are plenty of tutorials online, which won't cost you a cent. If you are sufficiently self-driven and interested, you have no difficulty training yourself. The point to learn coding…
10 PHP code snippets to work with dates
Here we have some set of Useful PHP Snippets, which are useful for PHP Developers. In this tutorial we'll show you the 10 PHP date snippets you can use on…
8 Free PHP Books to Read in Summer 2018
In this article, we've listed 8 free PHP books that can help you to learn new approaches to solving problems and keep your skill up to date. Practical PHP Testing This book…