01 · THE IDEAREAD → TRY → LEARN
Why namespaces exist
As a project grows, two classes will eventually want the same short name. A shop might have an Invoice for billing and another Invoice for display. A namespace gives each class a prefix, so the full names differ even when the short names match.
A useful analogy is a filesystem. A file name alone depends on the current directory, a path with folders is relative to where you are, and an absolute path starts at the root. PHP resolves class names with the same three ideas.
Declaring a namespace
The namespace keyword names the namespace for the code that follows. It must be the first statement in the file, apart from declare. Backslashes separate the levels.
namespace App\Models;
class User
{
}
echo User::class, "\n";
echo \strlen('abc'), "\n";App\Models\User 3
The class is now really named App\Models\User. The ::class constant shows that full name. The leading backslash in \strlen is explained below.
Three ways to write a name
Inside the namespace Shop, a class name can take three forms:
- Unqualified, such as
Invoice. PHP puts the current namespace in front, givingShop\Invoice. - Qualified, such as
Billing\Invoice. PHP still puts the current namespace in front, givingShop\Billing\Invoice. - Fully qualified, such as
\Shop\Billing\Invoice. The leading backslash means start at the root. The name is used literally.
The next example puts two classes in different namespaces and refers to them in all three ways. It uses the braced namespace form, where each namespace has its own block.
namespace Shop\Billing {
class Invoice
{
public function label(): string
{
return 'billing invoice';
}
}
}
namespace Shop {
class Invoice
{
public function label(): string
{
return 'shop invoice';
}
}
$a = new Invoice();
$b = new Billing\Invoice();
$c = new \Shop\Billing\Invoice();
echo $a::class, ': ', $a->label(), "\n";
echo $b::class, ': ', $b->label(), "\n";
echo $c::class, ': ', $c->label(), "\n";
}Shop\Invoice: shop invoice Shop\Billing\Invoice: billing invoice Shop\Billing\Invoice: billing invoice
The qualified name and the fully qualified name end up at the same class. The unqualified name stays in Shop.
Reaching global classes
Built-in classes such as Exception live in the global namespace. Inside a namespace, an unqualified Exception means a class in your own namespace. To reach the built-in one, write \Exception.
namespace App;
class Exception extends \Exception
{
}
$local = new Exception('local');
$global = new \Exception('global');
echo $local::class, "\n";
echo $global::class, "\n";
echo $local instanceof \Exception ? 'yes' : 'no', "\n";App\Exception Exception yes
The two classes are different, but the local one extends the global one, so the instanceof check succeeds.
Functions and constants behave a little differently. An unqualified function or constant name falls back to the global one if no namespaced version exists. Classes have no such fallback. Writing \strlen() is still a clear way to say that you mean the global function.
Worked reasoning
Take the current namespace App and the name Models\User. It does not start with a backslash, so it is relative. The result is App + \ + Models\User, which is App\Models\User. Now take \Exception. It starts with a backslash, so you drop that first character and get Exception. If the code is global and the current namespace is empty, a relative name is already complete, so no prefix is added.
Exercise contract
Write resolveClassName(string $currentNamespace, string $name): string. It should return the full class name, without a leading backslash, that PHP would use:
- If
$namestarts with a backslash, return it without that first character. - Otherwise, if
$currentNamespaceis an empty string, return$nameunchanged. - Otherwise, return the namespace, a backslash, and then the name.
The function treats unqualified and qualified names the same way, because both are relative to the current namespace.
Recap
A namespace prefixes class names so that similar names can coexist. Unqualified and qualified names are resolved from the current namespace, and a leading backslash starts from the global root. Use \Exception or \strlen() when you mean the global element.
Classes
- Declare a namespace
- Refer to a class with a fully qualified name