Understanding PHP Namespaces
PHP namespaces are a way of encapsulating items, such as classes, functions, and constants, within a logical structure. They are used to prevent naming
A namespace is a way of grouping related classes, interfaces, functions, and constants under a single logical name. Think of it like folders on your disk: two files named index.php can coexist as long as they live in different folders. In the same way, two classes named User can coexist as long as they live in different namespaces.
Without namespaces, every name lives in one shared global space. The moment your project and a third-party library both define a class called Logger or Router, PHP throws a fatal Cannot declare class error. Namespaces are the standard solution to that problem, and they are the foundation of Composer autoloading (the PSR-4 standard) used by virtually every modern PHP package.
Why Namespaces Matter
- Avoid naming collisions. Two pieces of code can use the same class or function name as long as they sit in different namespaces, so your code never clashes with a library's code.
- Organize large codebases. Namespaces mirror your folder structure, making it obvious where a class lives (
App\Service\Maileris inapp/Service/Mailer.php). - Enable autoloading. PSR-4 maps a namespace prefix to a directory, so Composer can load classes on demand without manual
requirestatements.
Defining a Namespace
Declare a namespace with the namespace keyword. It must be the very first statement in the file (only a declare(strict_types=1) line may come before it). Namespace names use a backslash (\) to separate levels:
<?php
namespace App\Service;
class Mailer
{
public function send(string $to): string
{
return "Mail sent to {$to}";
}
}Everything declared below the namespace line — the Mailer class — now lives in App\Service. Its fully qualified name is App\Service\Mailer.
Referencing Namespaced Items
There are three ways to refer to a name from another namespace.
A fully qualified name starts with a leading \ and names the item from the global root — it is unambiguous everywhere:
<?php
$mailer = new \App\Service\Mailer();A qualified name is relative to the current namespace, so Service\Mailer inside namespace App resolves to App\Service\Mailer. A name without any backslash is unqualified and is looked up in the current namespace first.
Importing With use
Writing the full path every time is tedious. The use keyword imports a name into the current file so you can reference it by its short name:
<?php
use App\Service\Mailer;
$mailer = new Mailer(); // resolves to App\Service\MailerAliasing With as
When two imported classes share a short name, give one an alias with as to disambiguate:
<?php
use App\Service\Mailer;
use Vendor\Mail\Mailer as VendorMailer;
$a = new Mailer(); // App\Service\Mailer
$b = new VendorMailer(); // Vendor\Mail\MailerImporting Functions and Constants
use imports classes by default. To import a function or a constant, add the function or const keyword:
<?php
use function App\Helpers\format_price;
use const App\Config\TAX_RATE;Gotcha: Built-in Functions Need a Leading Backslash
Inside a namespace, an unqualified function or class name is resolved against the current namespace first. For built-in functions PHP falls back to the global version automatically, but for built-in classes it does not. So referencing core classes like Exception, DateTime, or PDO requires a leading backslash (or a use statement):
<?php
namespace App\Service;
// Wrong: PHP looks for App\Service\Exception, which doesn't exist.
// throw new Exception('boom');
// Right: leading backslash points to the global class.
throw new \Exception('boom');A common, readable pattern is to import the core class at the top of the file instead:
<?php
namespace App\Service;
use Exception;
throw new Exception('boom'); // now the short name worksA Complete Example
This single, runnable script defines two namespaces and uses both — showing how the same short class name can live in two places without conflict:
<?php
namespace App\Billing {
class Invoice
{
public function label(): string
{
return 'Billing invoice';
}
}
}
namespace App\Shipping {
class Invoice
{
public function label(): string
{
return 'Shipping invoice';
}
}
}
namespace Main {
use App\Billing\Invoice;
use App\Shipping\Invoice as ShippingInvoice;
$billing = new Invoice();
$shipping = new ShippingInvoice();
echo $billing->label() . "\n";
echo $shipping->label() . "\n";
}Output:
Billing invoice
Shipping invoiceThe bracketed
namespace Foo { ... }syntax is only used to put multiple namespaces in one file (handy for a self-contained example). In real projects you put one namespace per file and rely on Composer autoloading.
Namespaces and Autoloading (PSR-4)
In practice you rarely write the namespace boundaries by hand for every file — Composer does the wiring. A PSR-4 mapping in composer.json ties a namespace prefix to a folder:
{
"autoload": {
"psr-4": {
"App\\": "src/"
}
}
}With this in place, the class App\Service\Mailer is automatically loaded from src/Service/Mailer.php the first time you reference it — no manual include or require needed.
Summary
- A namespace groups classes, interfaces, functions, and constants to prevent name collisions and organize code.
- Declare it with
namespace App\Service;as the first statement in the file. - Reference items by their fully qualified name (
\App\Service\Mailer) or, more commonly, import them withuseand refer to the short name. - Alias clashing names with
as, and remember to prefix global classes like\Exceptionwith a backslash inside a namespace. - PSR-4 autoloading maps a namespace prefix to a directory, which is how every Composer package is loaded.