In short: In PHP, namespaces are something like folders for class names: App\Rechnung\Pdf and Bibliothek\Pdf can exist side by side without interfering. Autoloading ensures that PHP loads a class only when it is needed for the first time. The PSR-4 standard defines how a class name becomes a file path; Composer then generates the matching autoloader. Because this autoloader runs on every request, it is among the first things to be checked after a security incident.
Why PHP needs namespaces
Namespaces have existed since PHP 5.3.0. Before that, all classes and functions shared a single global namespace. If two libraries were both called Logger, things crashed. Developers helped themselves with long names such as Firma_Modul_Unterbereich_Logger.
The PHP manual names two problems that namespaces solve: name collisions between your own code, PHP-internal classes and third-party libraries, and overlong names that arose only to work around those collisions. For decision-makers this means: only namespaces made it practical to combine dozens of third-party packages in one project, as is common today with Composer.
Namespaces in practice: namespace, use, aliases
A file declares its namespace in its first statement. With use, you pull classes in from other namespaces, under a shorter name if you wish.
<?php
declare(strict_types=1);
namespace App\Rechnung;
use App\Kunde\Kunde;
use Psr\Log\LoggerInterface as Log;
final class PdfErzeuger
{
public function __construct(private Log $log) {}
public function erzeugen(Kunde $kunde): string
{
$this->log->info('PDF erzeugt', ['kunde' => $kunde->id]);
return \sprintf('Rechnung für %s', $kunde->name);
}
}
The full name of this class is App\Rechnung\PdfErzeuger. The leading backslash in \sprintf explicitly refers to the global PHP function.
Autoloading: loading classes on demand
Without autoloading, every script would have to include all required files with require. With spl_autoload_register(), you instead register a function that PHP calls as soon as an unknown class, interface, trait or enum is used. It receives the class name and loads the matching file.
<?php
spl_autoload_register(function (string $klasse): void {
$praefix = 'App\\';
$basis = __DIR__ . '/src/';
if (!str_starts_with($klasse, $praefix)) {
return; // not responsible, the next autoloader's turn
}
$datei = $basis . str_replace('\\', '/', substr($klasse, strlen($praefix))) . '.php';
if (is_file($datei)) {
require $datei;
}
});
spl_autoload_register() can be called several times. PHP then asks the registered autoloaders one after another until one has loaded the class. In practice, large applications often have several: the Composer autoloader for libraries, one of the CMS itself and others from plugins or modules. For admins this means: which code is actually loaded during a request results from the interplay of all these autoloaders and not from the folder structure alone.
The manual strongly advises against throwing exceptions in an autoloader; PSR-4 explicitly forbids it. The older function __autoload() was deprecated in PHP 7.2.0 and removed in PHP 8.0.0.
PSR-4: from class name to file path
PSR-4 is a PHP-FIG standard. A fully qualified class name begins with a vendor namespace. A prefix of the namespace is assigned to a base directory, the rest of the name yields subfolders, and the file ends in .php. Upper and lower case must match exactly. This is what the mapping looks like in composer.json:
{
"autoload": {
"psr-4": { "App\\": "src/" }
}
}
| Class name | File |
|---|---|
App\Kunde\Kunde |
src/Kunde/Kunde.php |
App\Rechnung\PdfErzeuger |
src/Rechnung/PdfErzeuger.php |
App\Rechnung\Pdf\Vorlage |
src/Rechnung/Pdf/Vorlage.php |
A classic stumbling block is letter case. On development machines running Windows or macOS, the file system often does not distinguish between Kunde.php and kunde.php, but on a Linux server it does. An application that runs locally then fails to find a class on the server. The PSR-4 rule to use names in exactly the right spelling prevents such surprises at deployment.
Besides psr-4, Composer offers classmap for code without a standard structure and files for files that are loaded on every request, such as helper functions. Further PHP-FIG standards are described on the page PSR standards.
Optimising the autoloader in production
In production, the autoloader should ideally no longer search the file system but look things up in a ready-made list. Composer offers two levels for this:
composer install --no-dev --optimize-autoloaderconverts the PSR-4 rules into a class list. According to the Composer documentation, this is recommended for production.--classmap-authoritativegoes further: classes are loaded exclusively from the list. The autoloader then does not load files that are not listed at all.- With every deployment the list is regenerated so that new classes are found.
Autoloading and security after PHP2Shell
PHP2Shell affects the PHP interpreter, not the autoloader. The update to PHP 8.5.12, 8.4.27, 8.3.36 or 8.2.35 and the restart of all workers remain mandatory. After a possible incident, however, the autoloader deserves particular attention: vendor/autoload.php and all files listed under files are executed on every request. A line injected there therefore takes effect across the whole website, without a conspicuous new file sitting in the upload folder.
Check, therefore, whether vendor and the autoload files match the verified state from version control. The articles Finding recently changed files and Comparing CMS core files with the original are helpful. When in doubt, a freshly generated vendor from the lock file is safer than any individual repair.
How does PHP SOS help?
- We compare
vendor, the autoloader and entry files with the verified state and flag every deviation. - We restore the package set from the lock file and set up an optimised autoloader.
- We check whether only the public folder sits in the web root and source code is not directly reachable via URL.
- In case of infection, we carry out the cleanup as part of malware removal and document the result.
Frequently asked questions
Since when have there been namespaces in PHP?
Since PHP 5.3.0. According to the manual, they solve two problems: name collisions between your own code, PHP and third-party libraries, and overlong class names that arose only to avoid such collisions.
What is the difference between PSR-0 and PSR-4?
Both map class names to file paths. With PSR-4, the namespace prefix is not repeated in the file path, which results in flatter directories. PSR-0 is classified as deprecated by the PHP-FIG; PSR-4 is the recommended standard.
Does __autoload() still work?
No. __autoload() was deprecated in PHP 7.2.0 and removed in PHP 8.0.0. Today autoloaders are registered with spl_autoload_register(), in practice usually via the autoloader generated by Composer.
Do I have to regenerate the autoloader after creating a new class?
Not with pure PSR-4 rules; according to the Composer documentation this is precisely an advantage of PSR-4. If you use an optimised class list in production, you must regenerate it with every deployment.