What are namespaces? In the broadest definition namespaces are a way of encapsulating items. This can be seen as an abstract concept in many places.
For example, in any operating system directories serve to group related files, and act as a namespace for the files within them. As a concrete example, the file foo.txt can exist in both directory /home/greg and in /home/other, but two copies of foo.txt cannot co-exist in the same directory. In addition, to access the foo.txt file outside of the /home/greg directory, we must prepend the directory name to the file name using the directory separator to get /home/greg/foo.txt. This same principle extends to namespaces in the programming world!
In the PHP world, namespaces are designed to solve two problems that authors of libraries and applications encounter when creating re-usable code elements such as classes or functions:
- Name collisions between code you create, and internal PHP classes/functions/constants or third-party classes/functions/constants.
- Ability to alias (or shorten) Extra_Long_Names designed to alleviate the first problem, improving readability of source code.
PHP Namespaces provide a way in which to group related classes, interfaces, functions and constants. Here is an example of namespace syntax in PHP:
<?php namespace my\name; // see "Defining Namespaces" section class MyClass {} function myfunction() {} const MYCONST = 1; $a = new MyClass; $c = new \my\name\MyClass; // see "Global Space" section $a = strlen('hi'); // see "Using namespaces: fallback to global // function/constant" section $d = namespace\MYCONST; // see "namespace operator and __NAMESPACE__ // constant" section $d = __NAMESPACE__ . '\MYCONST'; echo constant($d); // see "Namespaces and dynamic language features" section ?>
Note: Namespace names are case-insensitive.
Although any valid PHP code can be contained within a namespace, only the following types of code are affected by namespaces: classes (including abstracts and traits), interfaces, functions and constants.
Namespaces are declared using the namespace keyword. A file containing a namespace must declare the namespace at the top of the file before any other code – with one exception: the declare keyword.
<?php namespace MyProject; const CONNECT_OK = 1; class Connection { /* ... */ } function connect() { /* ... */ } ?>
The only code construct allowed before a namespace declaration is the declare statement, for defining encoding of a source file. In addition, no non-PHP code may precede a namespace declaration, including extra whitespace:
<html> <?php namespace MyProject; // fatal error - namespace must be the first statement in the script ?>
In addition, unlike any other PHP construct, the same namespace may be defined in multiple files, allowing splitting up of a namespace’s contents across the filesystem.
Example Usage
Let’s take Karani–it’s a CRM with a financial component, so it tracks donors and receipts, among many other things.
Let’s set Karani
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, Karani\Billing
and Karani\Contacts
.
Let’s make a class or two in each:
<?php namespace Karani\Billing; class Receipt {}
<?php namespace Karani\Billing; class Subscription{}
<?php namespace Karani\Contacts; class Donor {}
So, we’re picturing a directory structure like this:
Karani Billing Receipt Subscription Contacts Donor
Referencing other classes in the same namespace
So, if a Subscription can send a Receipt, it’s easy to refer to it:
<?php namespace Karani\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 Donor?
<?php namespace Karani\Contacts; class Donor { public function sendReceipt() { // This won't work! $receipt = new Receipt; } }
ou guessed it: This won’t work.
We’re in the Karani\Contacts
namespace, so when we wrote new Receipt
, PHP assumes we’re talking about Karani\Contacts\Receipt
. But that class doesn’t exist, and that’s not what we’re looking for.
So, you’ll get a Class Karani\Contacts\Receipt not found
error.
You might be tempted to modify it to instead say $receipt = new Karani\Billing\Receipt
–but even that won’t work. Since we’re in the Karani\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 Karani\Contacts\Karani\Billing\Receipt
, which also clearly doesn’t exist.
Instead, you have two options:
First, you can precede it with a slash to create its FQCN (Fully Qualified Class Name): $receipt = new \Karani\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 Karani\Contacts; use Karani\Billing\Receipt; class Donor { 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.
More on PHP Namespaces in a future tutorial….