Why Namespaces?
Before namespaces, two libraries with the same class name (Logger, Cache) couldn't coexist. Namespaces are PHP's solution: a unique path prefix on every class.
Declaring a Namespace
<?php
namespace App\Service; // first non-comment statement
class UserService {
public function find(int $id): ?User { /* ... */ }
}
The fully qualified name is now App\Service\UserService.
Importing with use
<?php
namespace App\Controller;
use App\Service\UserService;
use App\Model\User;
class UserController {
public function __construct(private UserService $service) {}
public function show(int $id): ?User {
return $this->service->find($id);
}
}
Aliasing with as
<?php
namespace App;
use App\Model\User as AppUser;
use Vendor\Lib\User as VendorUser;
function combine(AppUser $a, VendorUser $b): array { /* ... */ }
The Global Namespace
Built-in PHP functions/classes (like strlen, DateTime, Exception) live in the global namespace. From within a namespace, prefix them with \\ for an absolute reference:
<?php
namespace App\Service;
class UserService {
public function find(int $id): ?\App\Model\User {
$now = new \DateTimeImmutable(); // \ = global namespace
if (\strlen("x") === 1) { // explicit global call
// ...
}
}
}
// Cleaner: import them at the top
use DateTimeImmutable;
use App\Model\User;
Sub-Namespaces
Namespaces can be nested arbitrarily deep:
<?php
namespace App\Http\Middleware;
class CorsMiddleware { /* ... */ }
namespace App\Domain\Order\Event;
class OrderPlaced { /* ... */ }
Group use Declarations (PHP 7.0+)
<?php
// Before
use App\Model\User;
use App\Model\Post;
use App\Model\Comment;
// After - group use
use App\Model\{User, Post, Comment};
// With aliases
use App\Model\{User as Member, Post};
// Mixed - class, function, const
use App\Helper\{
function format,
const VERSION,
Logger,
};
PSR-4 & Composer Autoload
PSR-4 maps namespace prefixes to folders. Composer reads this from composer.json:
{
"autoload": {
"psr-4": {
"App\": "src/",
"App\Tests\": "tests/"
}
}
}
After running composer dump-autoload, you only need one require statement at the top of your app:
<?php
require __DIR__ . "/../vendor/autoload.php";
use App\Service\UserService;
use App\Http\Router;
$router = new Router();
// All classes load on-demand from src/
| Namespace | Maps to file |
|---|---|
App\\Service\\UserService | src/Service/UserService.php |
App\\Model\\User | src/Model/User.php |
App\\Tests\\UserTest | tests/UserTest.php |
PSR-4 autoloading requires it. Class UserService must be in file UserService.php - case-sensitive on Linux.