PHP Namespaces

Organize your classes with namespaces, import them with use, alias clashes with as, and wire it all up to Composer's PSR-4 autoloader.

Intermediate 7 min read 8 examples

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

PHPsrc/Service/UserService.php
<?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
<?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
<?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
<?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
<?php
namespace App\Http\Middleware;
class CorsMiddleware { /* ... */ }

namespace App\Domain\Order\Event;
class OrderPlaced { /* ... */ }

Group use Declarations (PHP 7.0+)

PHP
<?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:

JSONcomposer.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:

PHPpublic/index.php
<?php
require __DIR__ . "/../vendor/autoload.php";

use App\Service\UserService;
use App\Http\Router;

$router = new Router();
// All classes load on-demand from src/
NamespaceMaps to file
App\\Service\\UserServicesrc/Service/UserService.php
App\\Model\\Usersrc/Model/User.php
App\\Tests\\UserTesttests/UserTest.php
One class per file, file name = class name

PSR-4 autoloading requires it. Class UserService must be in file UserService.php - case-sensitive on Linux.

Next Steps

Frequently Asked Questions

Practically, yes. Any library, framework, or non-trivial app should namespace its classes. Tiny single-file scripts can skip it. Composer's autoloading depends on namespaces matching folder paths (PSR-4).

namespace declares "this file's code lives in namespace X". use imports a name from elsewhere into the current file so you can refer to it without the full path. They work together.

Yes - PSR-4 mandates it. App\Service\UserService lives at src/Service/UserService.php. This lets Composer autoload classes on demand without manual require calls.

Inside a namespace, PHP looks for unqualified function calls in the current namespace first. \strlen() explicitly says "the global function". It's slightly faster too because PHP can resolve it at compile time.

Technically yes (with bracketed syntax) but strongly discouraged - it breaks PSR-1. One namespace per file, one class per file is the universal convention.