Īsi: nosaukumvietas PHP ir kaut kas līdzīgs mapēm klašu nosaukumiem: App\Rechnung\Pdf un Bibliothek\Pdf var pastāvēt blakus, netraucējot cits citam. Autoloading nodrošina, ka PHP klasi ielādē tikai tad, kad tā pirmo reizi vajadzīga. Standarts PSR-4 nosaka, kā no klases nosaukuma rodas faila ceļš; Composer pēc tam izveido atbilstošu autoloader. Tā kā šis autoloader darbojas katrā pieprasījumā, pēc drošības incidenta tas ir starp pirmajām lietām, kas jāpārbauda.
Kāpēc PHP vajadzīgas nosaukumvietas
Nosaukumvietas ir kopš PHP 5.3.0. Iepriekš visas klases un funkcijas dalīja vienu globālu nosaukumu telpu. Ja divas bibliotēkas saucās Logger, sākās problēmas. Izstrādātāji palīdzēja sev ar gariem nosaukumiem, piemēram, Firma_Modul_Unterbereich_Logger.
PHP rokasgrāmata min divas problēmas, ko nosaukumvietas atrisina: nosaukumu sadursmes starp paša kodu, PHP iekšējām klasēm un trešo pušu bibliotēkām, kā arī pārāk garus nosaukumus, kas radās tikai šo sadursmju apiešanai. Lēmumu pieņēmējiem tas nozīmē: tikai nosaukumvietas ļāva praktiski apvienot vienā projektā desmitiem svešu pakotņu, kā tas šodien ir ierasts ar Composer.
Nosaukumvietas praksē: namespace, use, aizstājvārdi
Fails savu nosaukumvietu deklarē pirmajā priekšrakstā. Ar use var ievilkt klases no citām nosaukumvietām, ja vēlas, ar īsāku nosaukumu.
<?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);
}
}
Šīs klases pilnais nosaukums ir App\Rechnung\PdfErzeuger. Sākuma atpakaļsvītra pie \sprintf skaidri norāda uz globālo PHP funkciju.
Autoloading: klašu ielāde pēc vajadzības
Bez autoloading katram skriptam visi nepieciešamie faili būtu jāpievieno ar require. Ar spl_autoload_register() tā vietā reģistrē funkciju, ko PHP izsauc, tiklīdz tiek izmantota nezināma klase, interfeiss, trait vai enum. Tā saņem klases nosaukumu un ielādē atbilstošo failu.
<?php
spl_autoload_register(function (string $klasse): void {
$praefix = 'App\\';
$basis = __DIR__ . '/src/';
if (!str_starts_with($klasse, $praefix)) {
return; // nav atbildīgs, nākamais autoloader
}
$datei = $basis . str_replace('\\', '/', substr($klasse, strlen($praefix))) . '.php';
if (is_file($datei)) {
require $datei;
}
});
spl_autoload_register() var izsaukt vairākkārt. PHP tad jautā reģistrētajiem autoloader pa vienam, līdz kāds klasi ielādē. Praksē lielām lietojumprogrammām to bieži ir vairāki: Composer autoloader bibliotēkām, paša CMS autoloader un citi no spraudņiem vai moduļiem. Administratoriem tas nozīmē: kāds kods pieprasījumā patiešām tiek ielādēts, izriet no visu šo autoloader sadarbības, nevis tikai no mapju struktūras.
Rokasgrāmata stingri iesaka autoloader nemest izņēmumus; PSR-4 to skaidri aizliedz. Vecākā funkcija __autoload() ar PHP 7.2.0 tika atzīta par novecojušu un ar PHP 8.0.0 noņemta.
PSR-4: no klases nosaukuma uz faila ceļu
PSR-4 ir PHP-FIG standarts. Pilns klases nosaukums sākas ar ražotāja nosaukumvietu. Nosaukumvietas prefikss tiek piesaistīts bāzes direktorijam, pārējā nosaukuma daļa dod apakšmapes, un fails beidzas ar .php. Lielajiem un mazajiem burtiem jāsakrīt precīzi. Šādi piesaiste izskatās failā composer.json:
{
"autoload": {
"psr-4": { "App\\": "src/" }
}
}
| Klases nosaukums | Fails |
|---|---|
App\Kunde\Kunde |
src/Kunde/Kunde.php |
App\Rechnung\PdfErzeuger |
src/Rechnung/PdfErzeuger.php |
App\Rechnung\Pdf\Vorlage |
src/Rechnung/Pdf/Vorlage.php |
Klasisks klupšanas akmens ir lielo un mazo burtu rakstība. Izstrādes datoros ar Windows vai macOS failu sistēma bieži nešķir Kunde.php un kunde.php, Linux serverī gan. Lietojumprogramma, kas lokāli darbojas, serverī tad klasi neatrod. PSR-4 noteikums lietot nosaukumus tieši pareizā rakstībā novērš šādus pārsteigumus piegādes laikā.
Līdzās psr-4 Composer pazīst classmap kodam bez standarta struktūras un files failiem, kas tiek ielādēti katrā pieprasījumā, piemēram, palīgfunkcijām. Citus PHP-FIG standartus apraksta lapa PSR standarti.
Autoloader optimizēšana produkcijā
Produkcijā autoloader vislabāk vairs nemeklē failu sistēmā, bet skatās gatavā sarakstā. Composer tam piedāvā divus līmeņus:
composer install --no-dev --optimize-autoloaderpārveido PSR-4 noteikumus klašu sarakstā. Saskaņā ar Composer dokumentāciju tas ir ieteicams produkcijai.--classmap-authoritativeiet tālāk: klases tiek ielādētas tikai no saraksta. Sarakstā neminētos failus autoloader tad nemaz neielādē.- Katrā piegādē saraksts tiek izveidots no jauna, lai jaunās klases tiktu atrastas.
Autoloading un drošība pēc PHP2Shell
PHP2Shell attiecas uz PHP interpretatoru, nevis uz autoloader. Obligāti paliek atjauninājums uz PHP 8.5.12, 8.4.27, 8.3.36 vai 8.2.35 un visu darbprocesu pārstartēšana. Pēc iespējama incidenta autoloader tomēr pelna īpašu uzmanību: vendor/autoload.php un visi zem files ierakstītie faili tiek izpildīti katrā pieprasījumā. Tur ievadīta rinda tātad iedarbojas uz visu vietni, un augšupielāžu mapē nav jābūt redzamam jaunam failam.
Tāpēc pārbaudiet, vai vendor un autoload faili atbilst pārbaudītajam stāvoklim no versiju pārvaldības. Noder raksti Nesen mainīto failu atrašana un CMS kodola failu salīdzināšana ar oriģinālu. Šaubu gadījumā no lock faila no jauna izveidots vendor ir drošāks nekā jebkurš atsevišķs labojums.
Kā PHP SOS palīdz konkrēti?
- Mēs salīdzinām
vendor, autoloader un ieejas failus ar pārbaudīto stāvokli un atzīmējam katru novirzi. - Mēs atjaunojam pakotņu kopumu no lock faila un iestatām optimizētu autoloader.
- Mēs pārbaudām, vai webroot atrodas tikai publiskā mape un avota kods nav tieši sasniedzams pa URL.
- Inficēšanas gadījumā mēs veicam attīrīšanu ļaunprogrammatūras noņemšanas ietvaros un dokumentējam rezultātu.
Biežāk uzdotie jautājumi
Kopš kura laika PHP ir nosaukumvietas?
Kopš PHP 5.3.0. Saskaņā ar rokasgrāmatu tās atrisina divas problēmas: nosaukumu sadursmes starp paša kodu, PHP un trešo pušu bibliotēkām, kā arī pārāk garus klašu nosaukumus, kas radās tikai, lai izvairītos no šādām sadursmēm.
Kāda ir atšķirība starp PSR-0 un PSR-4?
Abi attēlo klašu nosaukumus faila ceļos. PSR-4 gadījumā nosaukumvietas prefikss faila ceļā netiek atkārtots, tāpēc direktoriju struktūra ir plakanāka. PHP-FIG PSR-0 ir atzinusi par novecojušu, PSR-4 ir ieteicamais standarts.
Vai __autoload() joprojām darbojas?
Nē. __autoload() ar PHP 7.2.0 tika atzīta par novecojušu un ar PHP 8.0.0 noņemta. Šodien autoloader reģistrē ar spl_autoload_register(), praksē lielākoties ar Composer izveidoto autoloader.
Vai pēc jaunas klases izveides autoloader jāģenerē no jauna?
Tīru PSR-4 noteikumu gadījumā nē, saskaņā ar Composer dokumentāciju tā ir tieši PSR-4 priekšrocība. Kas produkcijā izmanto optimizētu klašu sarakstu, tas katrā piegādē jāizveido no jauna.