PSR-4 is a widely adopted standard for autoloading PHP classes and namespaces, defined by the PHP
Framework Interop Group (PHP-FIG). It allows you to load classes dynamically at runtime without
manually including files, using Composer’s autoloader or custom autoloaders.
What is PSR-4?
PSR-4 defines how namespace prefixes map to directory structures in your codebase. This enables
automatic class loading, reducing the need for manual require or include statements.
Key Benefits
- Automatic Class Loading: No need to include files manually.
- Namespace Support: Classes are organized into namespaces.
- Flexibility: One namespace can map to multiple directories.
- Composer Integration: Composer uses PSR-4 for class autoloading out of the box.
How PSR-4 Works
Namespace Prefix Mapping
You define a mapping like this in your composer.json:
"autoload": {
"psr-4": {
"App\\": "src/"
}
}
This means:
- All namespaces starting with
App\will be loaded from thesrc/directory. - For example,
App\Services\UserServicemaps tosrc/Services/UserService.php.
Naming and File Requirements
- Namespace structure must exactly match the folder hierarchy.
- Class name must match the file name (case-sensitive in some systems).
- Example:
– Class:App\Services\UserService
– File path:src/Services/UserService.php
– Inside class:class UserService
Complete PSR-4 Example
Directory Structure
project/
├── composer.json
└── src/
├── Services/
│ └── UserService.php
└── Repository/
└── UserRepository.php
composer.json
{
"name": "psr4-example/project",
"autoload": {
"psr-4": {
"App\\": "src/"
}
}
}
Run this after creating files:
composer dump-autoload
src/Services/UserService.php
<?php
namespace App\Services;
class UserService
{
private $repository;
public function __construct($repository)
{
$this->repository = $repository;
}
public function getUserById(int $id): array
{
return $this->repository->find($id);
}
}
src/Repository/UserRepository.php
<?php
namespace App\Repository;
class UserRepository
{
public function find(int $id): array
{
return ['id' => $id, 'name' => 'John Doe'];
}
}
public/index.php
<?php
require_once __DIR__ . '/../vendor/autoload.php';
use App\Services\UserService;
use App\Repository\UserRepository;
$repo = new UserRepository();
$userService = new UserService($repo);
$user = $userService->getUserById(123);
echo "User: " . htmlspecialchars($user['name']) . PHP_EOL;
Execution Output
$ php public/index.php
User: John Doe
PSR-4 vs. Other Standards
| Feature | PSR-0 | PSR-4 |
|---|---|---|
| Class Suffix | Required (_) | Optional |
| Directory Match | Strict | Flexible mapping |
| Prefix Mapping | Full namespace | Namespace prefix |
| Composer Support | Legacy | Standard |
Best Practices for PSR-4
- Use a Root Namespace: e.g.,
App\,Vendor\ - One-to-One File/Class Rule: Each file should define one class, matching the filename.
- Consistent Capitalization: Use camelCase for classes and PascalCase for namespaces.
- Use Composer Autoloader: Avoid custom autoloaders unless absolutely necessary.
Advanced Example: Multiple Namespaces
In composer.json:
{
"autoload": {
"psr-4": {
"App\\": "src/",
"Vendor\\Package\\": "packages/"
}
}
}
Directory structure:
project/
├── src/
│ └── App/
│ └── Services/
│ └── UserService.php
└── packages/
└── Vendor/
└── Package/
└── Utils/
└── Helper.php
Summary
- PSR-4 enables autoloading based on a namespace prefix and directory mapping.
- Class names must match file names, and the structure should reflect the namespace.
- Use Composer to manage autoloading in your projects.
- Follow PSR-4 conventions for clean, scalable PHP applications.
By adopting PSR-4, you ensure compatibility with modern PHP frameworks like Laravel and Symfony
and maintain a structured, autoloaded codebase.