Na kratko: Imenski prostori so v PHP nekaj podobnega mapam za imena razredov: App\Rechnung\Pdf in Bibliothek\Pdf lahko obstajata drug ob drugem, ne da bi si ovirala pot. Samodejno nalaganje poskrbi, da PHP razred naloži šele, ko ga prvič potrebuje. Standard PSR-4 določa, kako iz imena razreda nastane pot datoteke; Composer nato ustvari ustrezen nalagalnik. Ker ta nalagalnik teče ob vsaki zahtevi, sodi po varnostnem incidentu med prve stvari, ki jih je treba preveriti.
Zakaj PHP potrebuje imenske prostore
Imenski prostori obstajajo od PHP 5.3.0. Prej so si vsi razredi in funkcije delili en sam globalni imenski prostor. Če sta se dve knjižnici imenovali Logger, je počilo. Razvijalci so si pomagali z dolgimi imeni, kot je Firma_Modul_Unterbereich_Logger.
Priročnik PHP navaja dve težavi, ki ju rešujejo imenski prostori: trke imen med lastno kodo, notranjimi razredi PHP in knjižnicami tretjih ponudnikov ter predolga imena, ki so nastala samo za zaobhod teh trkov. Za odločevalce to pomeni: šele imenski prostori so omogočili praktično združevanje na desetine tujih paketov v enem projektu, kot je danes običajno s Composerjem.
Imenski prostori v praksi: namespace, use, vzdevki
Datoteka svoj imenski prostor deklarira v prvem ukazu. Z use se razredi iz drugih imenskih prostorov prinesejo noter, po želji pod krajšim imenom.
<?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);
}
}
Polno ime tega razreda je App\Rechnung\PdfErzeuger. Vodilna poševnica nazaj pri \sprintf izrecno kaže na globalno funkcijo PHP.
Samodejno nalaganje: nalaganje razredov po potrebi
Brez samodejnega nalaganja bi moral vsaka skripta vse potrebne datoteke vključiti z require. Z spl_autoload_register() se namesto tega registrira funkcija, ki jo PHP pokliče, brž ko se uporabi neznan razred, vmesnik, trait ali enum. Prejme ime razreda in naloži ustrezno datoteko.
<?php
spl_autoload_register(function (string $klasse): void {
$praefix = 'App\\';
$basis = __DIR__ . '/src/';
if (!str_starts_with($klasse, $praefix)) {
return; // ni pristojen, na vrsti je naslednji nalagalnik
}
$datei = $basis . str_replace('\\', '/', substr($klasse, strlen($praefix))) . '.php';
if (is_file($datei)) {
require $datei;
}
});
spl_autoload_register() je mogoče poklicati večkrat. PHP nato registrirane nalagalnike sprašuje zaporedoma, dokler eden ne naloži razreda. V praksi imajo velike aplikacije pogosto več nalagalnikov: nalagalnik Composer za knjižnice, lasten nalagalnik sistema CMS in druge od vtičnikov ali modulov. Za skrbnike to pomeni: katera koda se ob zahtevi dejansko naloži, izhaja iz sodelovanja vseh teh nalagalnikov, ne samo iz strukture map.
Priročnik izrecno odsvetuje sprožanje izjem v nalagalniku; PSR-4 to izrecno prepoveduje. Starejša funkcija __autoload() je bila s PHP 7.2.0 označena kot zastarela in s PHP 8.0.0 odstranjena.
PSR-4: od imena razreda do poti datoteke
PSR-4 je standard PHP-FIG. Polno ime razreda se začne z imenskim prostorom ponudnika. Predpona imenskega prostora se preslika v osnovni imenik, preostanek imena da podmape, datoteka pa se konča z .php. Velike in male črke se morajo natančno ujemati. Tako je videti preslikava v composer.json:
{
"autoload": {
"psr-4": { "App\\": "src/" }
}
}
| Ime razreda | 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 spodrsljaja so velike in male črke. Na razvojnih računalnikih z Windows ali macOS datotečni sistem pogosto ne razlikuje med Kunde.php in kunde.php, na strežniku Linux pa ju. Aplikacija, ki lokalno deluje, na strežniku razreda ne najde. Pravilo PSR-4, da se imena uporabljajo v natančno pravilnem zapisu, take presenečenja ob dostavi preprečuje.
Poleg psr-4 Composer pozna classmap za kodo brez standardne strukture in files za datoteke, ki se naložijo ob vsaki zahtevi, na primer pomožne funkcije. Druge standarde PHP-FIG opisuje stran Standardi PSR.
Optimizacija nalagalnika v produkciji
V produkciji nalagalnik najbolje ne išče več v datotečnem sistemu, temveč išče v že pripravljenem seznamu. Composer za to ponuja dve stopnji:
composer install --no-dev --optimize-autoloaderpravila PSR-4 pretvori v seznam razredov. To je po dokumentaciji Composerja za produkcijo priporočeno.--classmap-authoritativegre dlje: razredi se nalagajo izključno s seznama. Nalagalnik datotek, ki niso navedene, sploh ne naloži.- Ob vsaki dostavi se seznam ustvari znova, da se najdejo novi razredi.
Samodejno nalaganje in varnost po PHP2Shell
PHP2Shell zadeva interpreter PHP, ne nalagalnika. Obvezna ostaneta posodobitev na PHP 8.5.12, 8.4.27, 8.3.36 ali 8.2.35 in ponovni zagon vseh workerjev. Po morebitnem incidentu pa si nalagalnik zasluži posebno pozornost: vendor/autoload.php in vse datoteke, vpisane pod files, se izvedejo ob vsaki zahtevi. Tja vrinjena vrstica torej deluje na celotni spletni strani, ne da bi v mapi za nalaganje ležala kakšna opazna nova datoteka.
Zato preverite, ali vendor in datoteke nalagalnika ustrezajo preverjenemu stanju iz upravljanja različic. Koristna sta prispevka Iskanje nedavno spremenjenih datotek in Primerjava jedrnih datotek CMS z izvirnikom. Če ste v dvomih, je sveže ustvarjen vendor iz datoteke lock varnejši od vsakega posameznega popravila.
Kako PHP SOS pomaga konkretno?
vendor, nalagalnik in vstopne datoteke primerjamo s preverjenim stanjem in označimo vsako odstopanje.- Nabor paketov znova vzpostavimo iz datoteke lock in nastavimo optimiran nalagalnik.
- Preverimo, ali v korenu spleta (webroot) leži samo javna mapa in izvorna koda ni neposredno dosegljiva prek URL.
- Pri okužbi prevzamemo čiščenje v okviru odstranjevanja zlonamerne programske opreme in dokumentiramo rezultat.
Pogosta vprašanja
Od kdaj obstajajo imenski prostori v PHP?
Od PHP 5.3.0. Po priročniku rešujejo dve težavi: trke imen med lastno kodo, PHP in knjižnicami tretjih ponudnikov ter predolga imena razredov, ki so nastala samo zato, da bi se takim trkom izognili.
Kakšna je razlika med PSR-0 in PSR-4?
Oba preslikata imena razredov v poti datotek. Pri PSR-4 se predpona imenskega prostora v poti datoteke ne ponavlja, kar da bolj ploske imenike. PHP-FIG je PSR-0 uvrstil med zastarele, PSR-4 je priporočeni standard.
Ali __autoload() še deluje?
Ne. __autoload() je bil s PHP 7.2.0 označen kot zastarel, s PHP 8.0.0 pa odstranjen. Danes se nalagalniki registrirajo s spl_autoload_register(), v praksi večinoma prek nalagalnika, ki ga ustvari Composer.
Ali moram po ustvarjanju novega razreda nalagalnik ustvariti znova?
Pri čistih pravilih PSR-4 ne, po dokumentaciji Composerja je to ravno prednost PSR-4. Kdor v produkciji uporablja optimiran seznam razredov, ga mora ob vsaki dostavi ustvariti znova.