# Пространства от имена и autoloading (PSR-4)

> Namespaces и autoloading в PHP с PSR-4: от името на класа до пътя на файла, spl_autoload_register, autoloader на Composer и проверка след инциденти.

Източник: https://phpsos.de/bg/php/namespaces-autoloading/  
Актуалност: 25.10.2026  
Доставчик: PHP SOS, Спешна помощ за PHP и сигурност на сървъри. Незабавна помощ по WhatsApp: https://wa.me/491736494914?text=%D0%97%D0%B4%D1%80%D0%B0%D0%B2%D0%B5%D0%B9%D1%82%D0%B5%2C%20PHP%20SOS%2C%20%D0%B8%D0%BC%D0%B0%D0%BC%D0%B5%20%D0%BD%D1%83%D0%B6%D0%B4%D0%B0%20%D0%BE%D1%82%20%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%20%D1%81%20%D0%BD%D0%B0%D1%88%D0%B8%D1%8F%20PHP%20%D1%81%D1%8A%D1%80%D0%B2%D1%8A%D1%80.%20%D0%A4%D0%B8%D1%80%D0%BC%D0%B0%3A%20%E2%80%A6%20%D0%A3%D0%B5%D0%B1%D1%81%D0%B0%D0%B9%D1%82%3A%20%E2%80%A6

**Накратко:** Пространствата от имена (namespaces) в PHP са нещо като папки за имена на класове: `App\Rechnung\Pdf` и `Bibliothek\Pdf` могат да съществуват едно до друго, без да си пречат. Autoloading гарантира, че PHP зарежда един клас едва когато той бъде нужен за първи път. Стандартът PSR-4 определя как от името на клас се получава път до файл; след това Composer генерира подходящия autoloader. Тъй като този autoloader се изпълнява при всяка заявка, след инцидент със сигурността той е сред първите неща, които се проверяват.

## Защо PHP се нуждае от пространства от имена

Пространства от имена има от PHP 5.3.0. Преди това всички класове и функции споделяха едно-единствено глобално пространство от имена. Ако две библиотеки се наричаха `Logger`, възникваше сблъсък. Разработчиците си помагаха с дълги имена като `Firma_Modul_Unterbereich_Logger`.

Ръководството на PHP посочва два проблема, които пространствата от имена решават: колизии на имена между собствен код, вътрешни класове на PHP и библиотеки на трети страни, както и прекалено дълги имена, възникнали само за да се заобикалят тези колизии. За вземащите решения това означава: едва пространствата от имена направиха практически възможно да се комбинират десетки чужди пакети в един проект, както днес е обичайно с [Composer](https://phpsos.de/bg/php/composer/).

## Пространствата от имена на практика: namespace, use, псевдоними

Един файл декларира своето пространство от имена в първата инструкция. С `use` се внасят класове от други пространства от имена, по желание под по-кратко име.

```php
<?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);
    }
}
```

Пълното име на този клас е `App\Rechnung\PdfErzeuger`. Водещата обратна наклонена черта при `\sprintf` изрично сочи към глобалната функция на PHP.

## Autoloading: зареждане на класовете при нужда

Без autoloading всеки скрипт би трябвало да включва всички необходими файлове с `require`. Със `spl_autoload_register()` вместо това се регистрира функция, която PHP извиква, щом бъде използван непознат клас, интерфейс, trait или enum. Тя получава името на класа и зарежда подходящия файл.

```php
<?php
spl_autoload_register(function (string $klasse): void {
    $praefix = 'App\\';
    $basis   = __DIR__ . '/src/';

    if (!str_starts_with($klasse, $praefix)) {
        return; // не е компетентен, на ред е следващият autoloader
    }
    $datei = $basis . str_replace('\\', '/', substr($klasse, strlen($praefix))) . '.php';
    if (is_file($datei)) {
        require $datei;
    }
});
```

`spl_autoload_register()` може да се извиква многократно. PHP тогава пита регистрираните autoloader-и един след друг, докато някой зареди класа. На практика големите приложения често имат няколко: autoloader-а на Composer за библиотеките, собствен на CMS и още такива от плъгини или модули. За администраторите това означава: кой код действително се зарежда при една заявка, е резултат от взаимодействието на всички тези autoloader-и, а не само от структурата на папките.

Ръководството настоятелно съветва в autoloader да не се хвърлят изключения; PSR-4 го забранява изрично. По-старата функция `__autoload()` беше обявена за остаряла с PHP 7.2.0 и премахната с PHP 8.0.0.

## PSR-4: от името на класа до пътя на файла

PSR-4 е стандарт на PHP-FIG. Пълното име на клас започва с пространство от имена на производителя. Префикс на пространството от имена се съпоставя с базова директория, остатъкът от името дава поддиректории, а файлът завършва на `.php`. Главните и малките букви трябва да съвпадат точно. Така изглежда съпоставянето в `composer.json`:

```json
{
    "autoload": {
        "psr-4": { "App\\": "src/" }
    }
}
```

| Име на клас | Файл |
|---|---|
| `App\Kunde\Kunde` | `src/Kunde/Kunde.php` |
| `App\Rechnung\PdfErzeuger` | `src/Rechnung/PdfErzeuger.php` |
| `App\Rechnung\Pdf\Vorlage` | `src/Rechnung/Pdf/Vorlage.php` |

Класическа спънка е регистърът на буквите. На машини за разработка с Windows или macOS файловата система често не прави разлика между `Kunde.php` и `kunde.php`, а на Linux сървър прави. Приложение, което работи локално, тогава не намира на сървъра даден клас. Правилото на PSR-4 имената да се изписват точно в правилната форма предотвратява такива изненади при внедряване.

Освен `psr-4` Composer познава `classmap` за код без стандартна структура и `files` за файлове, които се зареждат при всяка заявка, например помощни функции. Други стандарти на PHP-FIG описва страницата [PSR стандарти](https://phpsos.de/bg/php/psr-standards/).

## Оптимизиране на autoloader-а в продукция

В продукция най-добре autoloader-ът вече не търси във файловата система, а справя в готов списък. Composer предлага за това две степени:

1. `composer install --no-dev --optimize-autoloader` превръща правилата на PSR-4 в списък на класовете. Според документацията на Composer това е препоръчително за продукция.
2. `--classmap-authoritative` отива по-далеч: класовете се зареждат изключително от списъка. Файлове, които не са в него, autoloader-ът изобщо не зарежда.
3. При всяко внедряване списъкът се генерира наново, за да бъдат намирани новите класове.

## Autoloading и сигурност след PHP2Shell

PHP2Shell засяга интерпретатора на PHP, а не autoloader-а. Задължителни остават актуализацията до PHP 8.5.12, 8.4.27, 8.3.36 или 8.2.35 и рестартирането на всички worker процеси. След възможен инцидент обаче autoloader-ът заслужава особено внимание: `vendor/autoload.php` и всички файлове, вписани под `files`, се изпълняват при всяка заявка. Внедрен там ред действа върху целия уебсайт, без в папката за качване да има нов, набиващ се на очи файл.

Затова проверете дали `vendor` и файловете на autoloader-а съвпадат с провереното състояние от системата за контрол на версиите. Полезни са статиите [Намиране на наскоро променени файлове](https://phpsos.de/bg/blog/geaenderte-dateien-finden/) и [Сравняване на ядрото на CMS с оригинала](https://phpsos.de/bg/blog/cms-kerndateien-vergleichen/). При съмнение наново генерираният `vendor` от lock файла е по-сигурен от всяка отделна поправка.

## Как помага PHP SOS конкретно?

- Сравняваме `vendor`, autoloader-а и входните файлове с провереното състояние и отбелязваме всяко отклонение.
- Възстановяваме наличността на пакетите от lock файла и настройваме оптимизиран autoloader.
- Проверяваме дали само публичната папка е в webroot и дали изходният код не е достъпен директно през URL.
- При заразяване поемаме почистването в рамките на [премахването на зловреден софтуер](https://phpsos.de/bg/leistungen/malware-entfernung/) и документираме резултата.


## Често задавани въпроси

**Откога има пространства от имена в PHP?**  
От PHP 5.3.0. Според ръководството те решават два проблема: колизии на имена между собствен код, PHP и библиотеки на трети страни, както и прекалено дълги имена на класове, възникнали само за да се избягват такива колизии.

**Каква е разликата между PSR-0 и PSR-4?**  
И двата съпоставят имена на класове с пътища до файлове. При PSR-4 префиксът на пространството от имена не се повтаря в пътя до файла, което дава по-плоски директории. PSR-0 е обявен от PHP-FIG за остарял, PSR-4 е препоръчаният стандарт.

**__autoload() още ли работи?**  
Не. __autoload() беше обявена за остаряла с PHP 7.2.0 и премахната с PHP 8.0.0. Днес autoloader-ите се регистрират със spl_autoload_register(), на практика най-често чрез autoloader-а, генериран от Composer.

**Трябва ли да генерирам наново autoloader-а след създаване на нов клас?**  
При чисти правила на PSR-4 не, според документацията на Composer това е именно предимство на PSR-4. Който в продукция използва оптимизиран списък на класовете, трябва да го генерира наново при всяко внедряване.

## Източници

- [PHP-FIG: PSR-4 Autoloader](https://www.php-fig.org/psr/psr-4/)
- [Ръководство на PHP: Пространства от имена, преглед](https://www.php.net/manual/de/language.namespaces.rationale.php)
- [Ръководство на PHP: Autoloading](https://www.php.net/manual/de/language.oop5.autoload.php)
- [Composer: The composer.json schema](https://getcomposer.org/doc/04-schema.md)
