Namespaces and Autoloading
Why Namespaces?
As projects grow, class and function name collisions become common. PHP namespaces (since PHP 5.3) provide a way to group related code and avoid naming conflicts — similar to packages in Java or modules in JavaScript.
Declaring a Namespace
<?php
namespace App\Models;
class User {
public function __construct(public string $name) {}
}
Every PHP file should declare one namespace at the top (after <?php), before any other code.
Using Namespaced Classes
<?php
use App\Models\User;
$user = new User('Alice');
Or reference with the fully qualified name:
$user = new \App\Models\User('Alice');
PSR-4 Autoloading
PSR-4 maps namespaces to directory structures. With Composer, define autoload rules in composer.json:
{
"autoload": {
"psr-4": {
"App\\": "src/"
}
}
}
Then run composer dump-autoload. Classes in src/Models/User.php with namespace App\Models load automatically — no manual require statements.
Best Practices
- Use one class per file, filename matching the class name
- Follow PSR-4 directory layout:
App\Controllers\UserController→src/Controllers/UserController.php - Prefer
useimports over long fully qualified names - Group related classes under meaningful namespace segments (
App\Services,App\Repositories)
Sub-namespaces and Aliases
use App\Models\User as UserModel;
use App\Models\Post;
$post = new Post();
$user = new UserModel('Bob');
Namespaces are the foundation for Composer, frameworks like Laravel and Symfony, and any maintainable PHP codebase.
Global Namespace and Functions
Functions and constants declared outside any namespace live in the global namespace. Reference them from within a namespace with a leading backslash:
<?php
namespace App\Services;
function helper() { return 'global'; }
class Mailer {
public function send(): void {
\mail('[email protected]', 'Subject', 'Body'); // PHP built-in
}
}
Dynamic Class Loading
Composer’s autoloader resolves classes at runtime. You rarely call require manually:
// composer.json maps App\ → src/
$user = new \App\Models\User('Alice'); // FQCN always works
Common Pitfalls
- Missing namespace declaration — classes default to the global namespace and may collide with framework classes.
- Wrong directory layout —
App\Models\Usermust live atsrc/Models/User.php, notsrc/User.php. - Forgetting
composer dump-autoloadafter adding new PSR-4 paths. - Using
useinside functions — placeusestatements at the top of the file after the namespace declaration.
Practical Exercise
- Create a project with
composer initand PSR-4 autoloading forApp\→src/. - Add
src/Models/User.phpandsrc/Repositories/UserRepository.php. - Write a script that instantiates the repository without any manual
requirecalls. - Add a sub-namespace
App\Services\Emailand confirm autoloading still works.
Related Topics
- Composer Package Management — dependency and autoload configuration
- PHP Standard Recommendations (PSRs) — PSR-4 specification details
- Laravel Framework — framework namespace conventions
Quick Reference
| Syntax | Example |
|---|---|
| Declare | namespace App\Models; |
| Import | use App\Models\User; |
| Alias | use App\Models\User as UserModel; |
| Global | \DateTime (leading backslash) |
| Function NS | namespace App\Utils; function helper() {} |
When in doubt, run composer dump-autoload -o and verify the class path matches the PSR-4 mapping exactly.