# Namespaceovi i autoloading (PSR-4)

> PHP namespaceovi i autoloading s PSR-4: od naziva klase do putanje datoteke, spl_autoload_register, Composerov autoloader i provjera nakon incidenata.

Izvor: https://phpsos.de/hr/php/namespaces-autoloading/  
Stanje: 25.10.2026  
Pružatelj: PHP SOS, PHP hitna pomoć i sigurnost poslužitelja. Hitna pomoć putem WhatsAppa: https://wa.me/491736494914?text=Pozdrav%20PHP%20SOS%2C%20trebamo%20pomo%C4%87%20s%20na%C5%A1im%20PHP%20poslu%C5%BEiteljem.%20Tvrtka%3A%20%E2%80%A6%20Web-stranica%3A%20%E2%80%A6

**Ukratko:** Namespaceovi su u PHP-u nešto poput mapa za nazive klasa: `App\Rechnung\Pdf` i `Bibliothek\Pdf` mogu postojati jedan uz drugi bez međusobnih smetnji. Autoloading osigurava da PHP klasu učita tek kad je prvi put zatreba. Standard PSR-4 određuje kako se iz naziva klase dobiva putanja datoteke; Composer zatim generira odgovarajući autoloader. Budući da se taj autoloader izvršava pri svakom zahtjevu, nakon sigurnosnog incidenta među prvim je stvarima koje se provjeravaju.

## Zašto PHP treba namespaceove

Namespaceovi postoje od PHP-a 5.3.0. Prije toga sve su klase i funkcije dijelile jedan jedini globalni prostor naziva. Ako su se dvije biblioteke zvale `Logger`, došlo je do sukoba. Programeri su si pomagali dugim nazivima poput `Firma_Modul_Unterbereich_Logger`.

PHP priručnik navodi dva problema koja namespaceovi rješavaju: sukobe naziva između vlastitog koda, internih PHP klasa i biblioteka trećih strana te preduge nazive nastale samo radi zaobilaženja tih sukoba. Za donositelje odluka to znači: tek su namespaceovi omogućili da se u jednom projektu praktično kombiniraju desetci stranih paketa, kako je danas uobičajeno uz [Composer](https://phpsos.de/hr/php/composer/).

## Namespaceovi u praksi: namespace, use, aliasi

Datoteka svoj namespace deklarira u prvoj naredbi. Pomoću `use` unose se klase iz drugih namespaceova, po želji pod kraćim nazivom.

```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);
    }
}
```

Puni naziv te klase glasi `App\Rechnung\PdfErzeuger`. Početna obrnuta kosa crta kod `\sprintf` izričito upućuje na globalnu PHP funkciju.

## Autoloading: učitavanje klasa prema potrebi

Bez autoloadinga svaka bi skripta morala uključiti sve potrebne datoteke s `require`. S `spl_autoload_register()` umjesto toga registrira se funkcija koju PHP poziva čim se upotrijebi nepoznata klasa, sučelje, trait ili enum. Ona dobiva naziv klase i učitava odgovarajuću datoteku.

```php
<?php
spl_autoload_register(function (string $klasse): void {
    $praefix = 'App\\';
    $basis   = __DIR__ . '/src/';

    if (!str_starts_with($klasse, $praefix)) {
        return; // nije nadležan, na redu je sljedeći autoloader
    }
    $datei = $basis . str_replace('\\', '/', substr($klasse, strlen($praefix))) . '.php';
    if (is_file($datei)) {
        require $datei;
    }
});
```

`spl_autoload_register()` može se pozvati više puta. PHP tada redom pita registrirane autoloadere dok jedan ne učita klasu. U praksi velike aplikacije često imaju nekoliko njih: Composerov autoloader za biblioteke, vlastiti autoloader CMS-a i dodatne od pluginova ili modula. Za administratore to znači: koji se kod pri zahtjevu doista učitava, proizlazi iz zajedničkog djelovanja svih tih autoloadera, a ne samo iz strukture direktorija.

Priručnik izričito odvraća od bacanja iznimki u autoloaderu; PSR-4 to izričito zabranjuje. Starija funkcija `__autoload()` označena je zastarjelom s PHP-om 7.2.0 i uklonjena s PHP-om 8.0.0.

## PSR-4: od naziva klase do putanje datoteke

PSR-4 je standard PHP-FIG-a. Puni naziv klase počinje namespaceom proizvođača. Prefiks namespacea pridružuje se baznom direktoriju, ostatak naziva daje podmape, a datoteka završava na `.php`. Velika i mala slova moraju se točno podudarati. Ovako izgleda pridruživanje u `composer.json`:

```json
{
    "autoload": {
        "psr-4": { "App\\": "src/" }
    }
}
```

| Naziv klase | Datoteka |
|---|---|
| `App\Kunde\Kunde` | `src/Kunde/Kunde.php` |
| `App\Rechnung\PdfErzeuger` | `src/Rechnung/PdfErzeuger.php` |
| `App\Rechnung\Pdf\Vorlage` | `src/Rechnung/Pdf/Vorlage.php` |

Klasična je spoticajna točka velika i mala slova. Na razvojnim računalima s Windowsom ili macOS-om datotečni sustav često ne razlikuje `Kunde.php` i `kunde.php`, a na Linux poslužitelju razlikuje. Aplikacija koja lokalno radi tada na poslužitelju ne pronalazi klasu. Pravilo iz PSR-4 da se nazivi koriste točno u ispravnom pisanju sprječava takva iznenađenja pri isporuci.

Uz `psr-4` Composer poznaje `classmap` za kod bez standardne strukture i `files` za datoteke koje se učitavaju pri svakom zahtjevu, primjerice pomoćne funkcije. Daljnje standarde PHP-FIG-a opisuje stranica [PSR standardi](https://phpsos.de/hr/php/psr-standards/).

## Optimiranje autoloadera u produkciji

U produkciji autoloader najbolje više ne traži po datotečnom sustavu, nego pogleda u gotov popis. Composer za to nudi dvije razine:

1. `composer install --no-dev --optimize-autoloader` pretvara PSR-4 pravila u popis klasa. Prema dokumentaciji Composera to se preporučuje za produkciju.
2. `--classmap-authoritative` ide dalje: klase se učitavaju isključivo s popisa. Datoteke koje nisu navedene autoloader tada uopće ne učitava.
3. Pri svakoj isporuci popis se ponovno generira kako bi se pronašle nove klase.

## Autoloading i sigurnost nakon PHP2Shella

PHP2Shell tiče se PHP interpretera, a ne autoloadera. Obveznima ostaju ažuriranje na PHP 8.5.12, 8.4.27, 8.3.36 ili 8.2.35 i ponovno pokretanje svih workera. Nakon mogućeg incidenta autoloader ipak zaslužuje posebnu pozornost: `vendor/autoload.php` i sve datoteke upisane pod `files` izvršavaju se pri svakom zahtjevu. Ondje ubačen redak stoga djeluje na cijelu web-stranicu, a da u direktoriju za upload ne leži nijedna upadljiva nova datoteka.

Provjerite stoga podudaraju li se `vendor` i datoteke autoloada s provjerenim stanjem iz sustava za kontrolu verzija. Korisni su članci [Pronalaženje nedavno izmijenjenih datoteka](https://phpsos.de/hr/blog/geaenderte-dateien-finden/) i [Usporedba temeljnih datoteka CMS-a s originalom](https://phpsos.de/hr/blog/cms-kerndateien-vergleichen/). U slučaju sumnje svježe generiran `vendor` iz lock datoteke sigurniji je od svakog pojedinačnog popravka.

## Kako PHP SOS konkretno pomaže?

- Uspoređujemo `vendor`, autoloader i ulazne datoteke s provjerenim stanjem i označavamo svako odstupanje.
- Iznova uspostavljamo skup paketa iz lock datoteke i postavljamo optimiran autoloader.
- Provjeravamo nalazi li se u webrootu samo javni direktorij te je li izvorni kod nedostupan izravno putem URL-a.
- U slučaju zaraze preuzimamo čišćenje u okviru [uklanjanja zlonamjernog softvera](https://phpsos.de/hr/leistungen/malware-entfernung/) i dokumentiramo rezultat.


## Česta pitanja

**Otkad u PHP-u postoje namespaceovi?**  
Od PHP-a 5.3.0. Prema priručniku rješavaju dva problema: sukobe naziva između vlastitog koda, PHP-a i biblioteka trećih strana te preduge nazive klasa koji su nastajali samo radi izbjegavanja takvih sukoba.

**Koja je razlika između PSR-0 i PSR-4?**  
Oba preslikavaju nazive klasa na putanje datoteka. Kod PSR-4 prefiks namespacea ne ponavlja se u putanji datoteke, što daje plošnije direktorije. PHP-FIG PSR-0 vodi kao zastario, a PSR-4 je preporučeni standard.

**Radi li __autoload() još?**  
Ne. __autoload() označen je zastarjelim s PHP-om 7.2.0, a uklonjen s PHP-om 8.0.0. Danas se autoloaderi registriraju funkcijom spl_autoload_register(), u praksi najčešće putem autoloadera koji generira Composer.

**Moram li nakon stvaranja nove klase ponovno generirati autoloader?**  
Kod čistih PSR-4 pravila ne, prema dokumentaciji Composera to je upravo prednost PSR-4. Tko u produkciji koristi optimiziran popis klasa, mora ga ponovno generirati pri svakoj isporuci.

## Izvori

- [PHP-FIG: PSR-4 autoloader](https://www.php-fig.org/psr/psr-4/)
- [PHP priručnik: Namespaceovi, pregled](https://www.php.net/manual/de/language.namespaces.rationale.php)
- [PHP priručnik: Autoloading](https://www.php.net/manual/de/language.oop5.autoload.php)
- [Composer: Shema datoteke composer.json](https://getcomposer.org/doc/04-schema.md)
