# Namespace-uri și autoloading (PSR-4)

> Namespace-uri PHP și autoloading cu PSR-4: de la numele clasei la calea fișierului, spl_autoload_register, autoloaderul Composer și verificarea după incidente.

Sursa: https://phpsos.de/ro/php/namespaces-autoloading/  
Stadiu: 25.10.2026  
Furnizor: PHP SOS, Asistență de urgență PHP și securitatea serverelor. Ajutor imediat pe WhatsApp: https://wa.me/491736494914?text=Bun%C4%83%20ziua%2C%20PHP%20SOS%2C%20avem%20nevoie%20de%20ajutor%20cu%20serverul%20nostru%20PHP.%20Firma%3A%20%E2%80%A6%20Site%3A%20%E2%80%A6

**Pe scurt:** Namespace-urile sunt în PHP un fel de foldere pentru numele de clase: `App\Rechnung\Pdf` și `Bibliothek\Pdf` pot exista unul lângă altul, fără să se deranjeze. Autoloading-ul face ca PHP să încarce o clasă abia când este nevoie de ea pentru prima dată. Standardul PSR-4 stabilește cum devine un nume de clasă o cale de fișier; Composer generează apoi autoloaderul potrivit. Deoarece acest autoloader rulează la fiecare cerere, el se numără după un incident de securitate printre primele lucruri verificate.

## De ce are PHP nevoie de namespace-uri

Namespace-uri există din PHP 5.3.0. Înainte, toate clasele și funcțiile împărțeau un singur spațiu de nume global. Dacă două biblioteci se numeau `Logger`, totul se oprea. Dezvoltatorii se descurcau cu nume lungi, precum `Firma_Modul_Unterbereich_Logger`.

Manualul PHP menționează două probleme pe care le rezolvă namespace-urile: coliziunile de nume între codul propriu, clasele interne ale PHP și bibliotecile terților, precum și numele prea lungi, apărute doar pentru ocolirea acestor coliziuni. Pentru factorii de decizie, aceasta înseamnă: abia namespace-urile au făcut practică combinarea a zeci de pachete străine într-un proiect, așa cum este astăzi uzual cu [Composer](https://phpsos.de/ro/php/composer/).

## Namespace-uri în practică: namespace, use, alias-uri

Un fișier își declară namespace-ul în prima instrucțiune. Cu `use` se aduc clase din alte namespace-uri, la cerere sub un nume mai scurt.

```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);
    }
}
```

Numele complet al acestei clase este `App\Rechnung\PdfErzeuger`. Backslash-ul de la început din `\sprintf` trimite în mod explicit la funcția PHP globală.

## Autoloading: încărcarea claselor la nevoie

Fără autoloading, fiecare script ar trebui să includă toate fișierele necesare cu `require`. Cu `spl_autoload_register()` se înregistrează în schimb o funcție pe care PHP o apelează de îndată ce este folosită o clasă, o interfață, un trait sau un enum necunoscut. Ea primește numele clasei și încarcă fișierul potrivit.

```php
<?php
spl_autoload_register(function (string $klasse): void {
    $praefix = 'App\\';
    $basis   = __DIR__ . '/src/';

    if (!str_starts_with($klasse, $praefix)) {
        return; // nu este responsabil, urmează următorul autoloader
    }
    $datei = $basis . str_replace('\\', '/', substr($klasse, strlen($praefix))) . '.php';
    if (is_file($datei)) {
        require $datei;
    }
});
```

`spl_autoload_register()` poate fi apelată de mai multe ori. PHP interoghează atunci autoloaderele înregistrate pe rând, până când unul încarcă clasa. În practică, aplicațiile mari au adesea mai multe: autoloaderul Composer pentru biblioteci, unul propriu al CMS-ului și altele ale plugin-urilor sau modulelor. Pentru administratori aceasta înseamnă: ce cod este efectiv încărcat la o cerere rezultă din conlucrarea tuturor acestor autoloadere, nu doar din structura folderelor.

Manualul descurajează ferm aruncarea de excepții într-un autoloader; PSR-4 o interzice explicit. Mai vechea funcție `__autoload()` a fost marcată ca depășită în PHP 7.2.0 și eliminată în PHP 8.0.0.

## PSR-4: de la numele clasei la calea fișierului

PSR-4 este un standard al PHP-FIG. Un nume complet de clasă începe cu un namespace de producător. Un prefix al namespace-ului este asociat unui director de bază, restul numelui dă subfolderele, iar fișierul se termină în `.php`. Majusculele și minusculele trebuie să coincidă exact. Așa arată asocierea în `composer.json`:

```json
{
    "autoload": {
        "psr-4": { "App\\": "src/" }
    }
}
```

| Numele clasei | Fișier |
|---|---|
| `App\Kunde\Kunde` | `src/Kunde/Kunde.php` |
| `App\Rechnung\PdfErzeuger` | `src/Rechnung/PdfErzeuger.php` |
| `App\Rechnung\Pdf\Vorlage` | `src/Rechnung/Pdf/Vorlage.php` |

O piedică clasică este diferența dintre majuscule și minuscule. Pe calculatoarele de dezvoltare cu Windows sau macOS, sistemul de fișiere nu face adesea distincție între `Kunde.php` și `kunde.php`, dar pe un server Linux o face. O aplicație care rulează local nu găsește atunci o clasă pe server. Regula din PSR-4 de a folosi numele exact în grafia corectă previne asemenea surprize la livrare.

Pe lângă `psr-4`, Composer cunoaște `classmap` pentru cod fără structură standard și `files` pentru fișiere încărcate la fiecare cerere, de exemplu funcții ajutătoare. Alte standarde ale PHP-FIG descrie pagina [Standardele PSR](https://phpsos.de/ro/php/psr-standards/).

## Optimizarea autoloaderului în producție

În producție, autoloaderul nu ar trebui să mai caute în sistemul de fișiere, ci să consulte o listă gata făcută. Composer oferă pentru aceasta două trepte:

1. `composer install --no-dev --optimize-autoloader` transformă regulile PSR-4 într-o listă de clase. Potrivit documentației Composer, aceasta este recomandată pentru producție.
2. `--classmap-authoritative` merge mai departe: clasele sunt încărcate exclusiv din listă. Fișierele nemenționate nu sunt încărcate deloc de autoloader.
3. La fiecare livrare lista este regenerată, pentru ca noile clase să fie găsite.

## Autoloading și securitate după PHP2Shell

PHP2Shell afectează interpretorul PHP, nu autoloaderul. Rămân obligatorii actualizarea la PHP 8.5.12, 8.4.27, 8.3.36 sau 8.2.35 și repornirea tuturor workerilor. După un posibil incident, autoloaderul merită însă o atenție deosebită: `vendor/autoload.php` și toate fișierele înscrise la `files` sunt executate la fiecare cerere. O linie strecurată acolo acționează deci asupra întregului site, fără ca un fișier nou, suspect, să se afle în folderul de upload.

Verificați de aceea dacă `vendor` și fișierele de autoload corespund stării verificate din controlul versiunilor. Utile sunt articolele [Găsirea fișierelor modificate recent](https://phpsos.de/ro/blog/geaenderte-dateien-finden/) și [Compararea fișierelor de bază ale CMS-ului cu originalul](https://phpsos.de/ro/blog/cms-kerndateien-vergleichen/). În caz de dubiu, un `vendor` proaspăt generat din fișierul lock este mai sigur decât orice reparație punctuală.

## Cum ajută PHP SOS concret?

- Comparăm `vendor`, autoloaderul și fișierele de intrare cu starea verificată și marcăm orice abatere.
- Refacem inventarul de pachete din fișierul lock și configurăm un autoloader optimizat.
- Verificăm dacă în webroot se află doar folderul public și dacă codul sursă nu este accesibil direct prin URL.
- În caz de infectare, preluăm curățarea în cadrul [eliminării malware-ului](https://phpsos.de/ro/leistungen/malware-entfernung/) și documentăm rezultatul.


## Întrebări frecvente

**De când există namespace-uri în PHP?**  
Din PHP 5.3.0. Potrivit manualului, ele rezolvă două probleme: coliziunile de nume între codul propriu, PHP și bibliotecile terților, precum și numele de clase prea lungi, apărute doar pentru a evita asemenea coliziuni.

**Care este diferența dintre PSR-0 și PSR-4?**  
Ambele asociază numele de clase cu căi de fișiere. La PSR-4, prefixul namespace-ului nu se repetă în calea fișierului, ceea ce dă directoare mai plate. PSR-0 este considerat depășit de PHP-FIG, iar PSR-4 este standardul recomandat.

**Mai funcționează __autoload()?**  
Nu. __autoload() a fost marcată ca depășită în PHP 7.2.0 și eliminată în PHP 8.0.0. Astăzi autoloaderele se înregistrează cu spl_autoload_register(), în practică de obicei prin autoloaderul generat de Composer.

**Trebuie să regenerez autoloaderul după crearea unei clase noi?**  
La reguli exclusiv PSR-4, nu; potrivit documentației Composer, tocmai acesta este un avantaj al PSR-4. Cine folosește în producție o listă optimizată de clase trebuie să o regenereze la fiecare livrare.

## Surse

- [PHP-FIG: autoloader PSR-4](https://www.php-fig.org/psr/psr-4/)
- [Manualul PHP: namespace-uri, privire de ansamblu](https://www.php.net/manual/de/language.namespaces.rationale.php)
- [Manualul PHP: autoloading](https://www.php.net/manual/de/language.oop5.autoload.php)
- [Composer: schema composer.json](https://getcomposer.org/doc/04-schema.md)
