Текуща ситуация: PHP2Shell. Две критични уязвимости в PHP (CVSS 9,2) позволяват злонамерен код без вход. Корекции от 21.10.2026 г.Какво да направите сега →

Пространства от имена и autoloading (PSR-4)

Пространствата от имена подреждат PHP кода, а autoloading зарежда класовете точно когато са нужни. Тук ще видите как PSR-4 съпоставя имената на класове с файлове и защо autoloader-ът трябва да се проверява след инцидент.

Актуалност 5 мин. четенеЗнания за PHP

Накратко: Пространствата от имена (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.

Пространствата от имена на практика: namespace, use, псевдоними

Един файл декларира своето пространство от имена в първата инструкция. С use се внасят класове от други пространства от имена, по желание под по-кратко име.

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

{
    "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 стандарти.

Оптимизиране на 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-а съвпадат с провереното състояние от системата за контрол на версиите. Полезни са статиите Намиране на наскоро променени файлове и Сравняване на ядрото на CMS с оригинала. При съмнение наново генерираният vendor от lock файла е по-сигурен от всяка отделна поправка.

Как помага PHP SOS конкретно?

  • Сравняваме vendor, autoloader-а и входните файлове с провереното състояние и отбелязваме всяко отклонение.
  • Възстановяваме наличността на пакетите от lock файла и настройваме оптимизиран autoloader.
  • Проверяваме дали само публичната папка е в webroot и дали изходният код не е достъпен директно през URL.
  • При заразяване поемаме почистването в рамките на премахването на зловреден софтуер и документираме резултата.

Често задавани въпроси

Откога има пространства от имена в 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 и какво сте забелязали. Ние се свързваме с Вас, уточняваме ситуацията и работим отдалечено, докато инцидентът бъде приключен и документиран.

Незабавна помощ