PHP Namespaces
As PHP applications grow larger and rely on third-party libraries, naming conflicts become a real problem. Two different packages might define a class called Logger, and including both would cause PHP to complain that the class is already defined. Namespaces solve this by organizing classes, functions, and constants into named groups — similar to how a filesystem uses folders to organize files with the same name. This is the reason every modern PHP framework uses namespaces throughout its codebase.
Declaring a Namespace
A namespace is declared at the very top of a PHP file, before any other code (except the opening PHP tag and comments).
<?php
namespace App\Models;
class User {
public string $name;
public string $email;
public function __construct(string $name, string $email) {
$this->name = $name;
$this->email = $email;
}
}
?>
<?php
namespace App\Models;
class Product {
public string $name;
public float $price;
public function __construct(string $name, float $price) {
$this->name = $name;
$this->price = $price;
}
}
?>
Both files use the same namespace. Classes in the same namespace can reference each other directly without any qualification.
Using a Namespaced Class
To use a class from another namespace, you reference it by its fully qualified name, which includes the namespace path.
<?php
namespace App\Controllers;
// Use the fully qualified name
$user = new \App\Models\User("Alice", "alice@example.com");
echo $user->name; // Alice
?>
The leading backslash \ signals that the namespace starts from the global root, not the current namespace.
The use Statement
Writing full namespace paths every time is tedious. The use statement imports a class into the current file so it can be referenced by its short name.
<?php
namespace App\Controllers;
use App\Models\User;
use App\Models\Product;
$user = new User("Alice", "alice@example.com");
$product = new Product("Laptop", 999.99);
echo $user->name . " bought " . $product->name;
?>
Aliasing with as
If two imported classes share the same short name, use as to give one of them an alias.
<?php
namespace App;
use App\Models\User as UserModel;
use Admin\Models\User as AdminUser;
$siteUser = new UserModel("Alice", "alice@example.com");
$adminUser = new AdminUser("Bob", "bob@admin.com");
?>
Namespacing Functions and Constants
Namespaces apply to functions and constants, not just classes.
<?php
namespace App\Utils;
const VERSION = "1.0.0";
function formatCurrency(float $amount, string $currency = "USD"): string {
return $currency . " " . number_format($amount, 2);
}
?>
<?php
namespace App;
use function App\Utils\formatCurrency;
use const App\Utils\VERSION;
echo VERSION; // 1.0.0
echo formatCurrency(1999.99); // USD 1,999.99
?>
Autoloading with Composer and PSR-4
Manually including every file with require is impractical in large projects. Composer's autoloader, following the PSR-4 standard, automatically includes the correct file based on the namespace and class name.
The convention maps namespace segments to directory paths. With this configuration in composer.json:
{
"autoload": {
"psr-4": {
"App\\": "src/"
}
}
}
The class App\Models\User must be in the file src/Models/User.php, and the class App\Controllers\HomeController must be in src/Controllers/HomeController.php.
project/
├── composer.json
├── src/
│ ├── Models/
│ │ ├── User.php (namespace App\Models)
│ │ └── Product.php (namespace App\Models)
│ └── Controllers/
│ └── HomeController.php (namespace App\Controllers)
└── public/
└── index.php
<?php
// public/index.php
require_once __DIR__ . "/../vendor/autoload.php"; // Load Composer's autoloader
use App\Models\User;
use App\Controllers\HomeController;
$user = new User("Alice", "alice@example.com");
// Composer automatically includes src/Models/User.php
?>
After updating composer.json, run composer dump-autoload in the terminal to regenerate the autoloader.
Global Namespace
PHP's built-in classes and functions belong to the global namespace. When inside a custom namespace, reference built-in classes with a leading backslash to avoid PHP looking for them inside the current namespace.
<?php
namespace App\Services;
class EmailService {
public function sendEmail(string $to, string $subject): void {
// \DateTime refers to PHP's built-in DateTime class
$date = new \DateTime();
$timestamp = $date->format("Y-m-d H:i:s");
// \Exception also refers to the global exception
if (empty($to)) {
throw new \InvalidArgumentException("Recipient email cannot be empty.");
}
echo "Email to $to sent at $timestamp.";
}
}
?>
Alternatively, add a use statement for the built-in class: use DateTime; — this is common in codebases that use namespaces throughout.
Key Points
- Namespaces prevent naming conflicts between classes, functions, and constants in large applications and third-party libraries.
- Declare a namespace with
namespace My\Namespace;at the top of the file, before any other code. - Use a class from another namespace with its fully qualified name (e.g.,
\App\Models\User) or import it withuse. - The
askeyword in ausestatement creates an alias for an imported class, function, or constant. - PSR-4 autoloading (via Composer) maps namespace segments to directory paths, automatically loading the correct file for any class.
- PHP's built-in classes live in the global namespace — prefix them with
\(e.g.,\DateTime) when inside a custom namespace.
