Τρέχουσα κατάσταση: PHP2Shell. Δύο κρίσιμες ευπάθειες της PHP (CVSS 9.2) επιτρέπουν κακόβουλο κώδικα χωρίς σύνδεση. Patches από τις 21/10/2026.Τι πρέπει να γίνει τώρα →

Namespaces και autoloading (PSR-4)

Τα namespaces οργανώνουν τον κώδικα PHP, το autoloading φορτώνει κλάσεις ακριβώς όταν χρειάζονται. Εδώ βλέπετε πώς το PSR-4 αντιστοιχίζει ονόματα κλάσεων σε αρχεία και γιατί ο autoloader πρέπει να ελέγχεται μετά από περιστατικό.

Ημερομηνία 5 λεπτά ανάγνωσηςΓνώση PHP

Εν συντομία: Τα namespaces είναι στην PHP κάτι σαν φάκελοι για ονόματα κλάσεων: οι App\Rechnung\Pdf και Bibliothek\Pdf μπορούν να συνυπάρχουν χωρίς να συγκρούονται. Το autoloading φροντίζει ώστε η PHP να φορτώνει μια κλάση μόνο όταν τη χρειαστεί για πρώτη φορά. Το πρότυπο PSR-4 ορίζει πώς από ένα όνομα κλάσης προκύπτει μια διαδρομή αρχείου· στη συνέχεια ο Composer δημιουργεί τον κατάλληλο autoloader. Επειδή αυτός ο autoloader εκτελείται σε κάθε αίτημα, ανήκει μετά από περιστατικό ασφαλείας στα πρώτα πράγματα που ελέγχονται.

Γιατί η PHP χρειάζεται namespaces

Τα namespaces υπάρχουν από την PHP 5.3.0. Πριν, όλες οι κλάσεις και οι συναρτήσεις μοιράζονταν έναν ενιαίο καθολικό χώρο ονομάτων. Αν δύο βιβλιοθήκες ονομάζονταν Logger, υπήρχε σύγκρουση. Οι προγραμματιστές βοηθούσαν τον εαυτό τους με μακριά ονόματα όπως Firma_Modul_Unterbereich_Logger.

Το εγχειρίδιο της PHP αναφέρει δύο προβλήματα που λύνουν τα namespaces: συγκρούσεις ονομάτων μεταξύ του δικού σας κώδικα, των εσωτερικών κλάσεων της PHP και βιβλιοθηκών τρίτων, καθώς και υπερβολικά μακριά ονόματα που δημιουργήθηκαν μόνο για την παράκαμψη αυτών των συγκρούσεων. Για όσους αποφασίζουν αυτό σημαίνει: μόνο τα namespaces κατέστησαν πρακτικό τον συνδυασμό δεκάδων ξένων πακέτων σε ένα έργο, όπως είναι σήμερα συνηθισμένο με τον Composer.

Namespaces στην πράξη: namespace, use, aliases

Ένα αρχείο δηλώνει το namespace του στην πρώτη εντολή. Με το use φέρνετε κλάσεις από άλλα namespaces, αν θέλετε με συντομότερο όνομα.

<?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 ρωτά τότε τους καταχωρισμένους autoloaders με τη σειρά, μέχρι να φορτώσει κάποιος την κλάση. Στην πράξη οι μεγάλες εφαρμογές έχουν συχνά περισσότερους από έναν: τον autoloader του Composer για βιβλιοθήκες, έναν δικό του του CMS και άλλους από πρόσθετα ή modules. Για τους διαχειριστές αυτό σημαίνει: ποιος κώδικας φορτώνεται πραγματικά σε ένα αίτημα προκύπτει από τη συνεργασία όλων αυτών των autoloaders και όχι μόνο από τη δομή των φακέλων.

Το εγχειρίδιο αποτρέπει έντονα την ρίψη exceptions μέσα σε έναν autoloader· το PSR-4 το απαγορεύει ρητά. Η παλαιότερη συνάρτηση __autoload() χαρακτηρίστηκε παρωχημένη με την PHP 7.2.0 και αφαιρέθηκε με την PHP 8.0.0.

PSR-4: από το όνομα κλάσης στη διαδρομή αρχείου

Το PSR-4 είναι πρότυπο του PHP-FIG. Ένα πλήρες όνομα κλάσης ξεκινά με ένα namespace κατασκευαστή. Ένα πρόθεμα του namespace αντιστοιχίζεται σε έναν βασικό κατάλογο, το υπόλοιπο του ονόματος δίνει υποφακέλους και το αρχείο τελειώνει σε .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 και η επανεκκίνηση όλων των workers. Μετά από ένα πιθανό περιστατικό, ο autoloader αξίζει όμως ιδιαίτερη προσοχή: το vendor/autoload.php και όλα τα αρχεία που έχουν καταχωριστεί στο files εκτελούνται σε κάθε αίτημα. Μια γραμμή που έχει εισαχθεί εκεί επηρεάζει επομένως ολόκληρο τον ιστότοπο, χωρίς να βρίσκεται κάποιο ύποπτο νέο αρχείο στον φάκελο μεταφορτώσεων.

Ελέγξτε γι' αυτό αν ο φάκελος vendor και τα αρχεία autoload ταιριάζουν με την ελεγμένη κατάσταση από τον έλεγχο εκδόσεων. Χρήσιμα είναι τα άρθρα Εντοπισμός πρόσφατα τροποποιημένων αρχείων και Σύγκριση των αρχείων πυρήνα του CMS με το πρωτότυπο. Σε περίπτωση αμφιβολίας, ένας φάκελος vendor που δημιουργείται εκ νέου από το lock αρχείο είναι ασφαλέστερος από κάθε μεμονωμένη επιδιόρθωση.

Πώς βοηθά συγκεκριμένα η PHP SOS;

  • Συγκρίνουμε το vendor, τον autoloader και τα αρχεία εισόδου με την ελεγμένη κατάσταση και επισημαίνουμε κάθε απόκλιση.
  • Αποκαθιστούμε εκ νέου το σύνολο πακέτων από το lock αρχείο και ρυθμίζουμε έναν βελτιστοποιημένο autoloader.
  • Ελέγχουμε αν στο webroot βρίσκεται μόνο ο δημόσιος φάκελος και αν ο πηγαίος κώδικας δεν είναι προσβάσιμος απευθείας μέσω URL.
  • Σε περίπτωση μόλυνσης αναλαμβάνουμε τον καθαρισμό στο πλαίσιο της αφαίρεσης κακόβουλου λογισμικού και τεκμηριώνουμε το αποτέλεσμα.

Συχνές ερωτήσεις

Από πότε υπάρχουν namespaces στην PHP;

Από την PHP 5.3.0. Σύμφωνα με το εγχειρίδιο λύνουν δύο προβλήματα: τις συγκρούσεις ονομάτων μεταξύ του δικού σας κώδικα, της PHP και βιβλιοθηκών τρίτων, καθώς και τα υπερβολικά μακριά ονόματα κλάσεων που δημιουργήθηκαν μόνο για να αποφεύγονται τέτοιες συγκρούσεις.

Ποια είναι η διαφορά μεταξύ PSR-0 και PSR-4;

Και τα δύο αντιστοιχίζουν ονόματα κλάσεων σε διαδρομές αρχείων. Στο PSR-4 το πρόθεμα του namespace δεν επαναλαμβάνεται στη διαδρομή του αρχείου, γεγονός που δίνει πιο επίπεδους καταλόγους. Το PSR-0 έχει χαρακτηριστεί ως παρωχημένο από το PHP-FIG, ενώ το PSR-4 είναι το συνιστώμενο πρότυπο.

Λειτουργεί ακόμη η __autoload();

Όχι. Η __autoload() χαρακτηρίστηκε παρωχημένη με την PHP 7.2.0 και αφαιρέθηκε με την PHP 8.0.0. Σήμερα οι autoloaders καταχωρίζονται με την spl_autoload_register(), στην πράξη συνήθως μέσω του autoloader που δημιουργεί ο Composer.

Πρέπει να δημιουργήσω ξανά τον autoloader μετά από τη δημιουργία μιας νέας κλάσης;

Με καθαρούς κανόνες PSR-4 όχι· σύμφωνα με την τεκμηρίωση του Composer αυτό είναι ακριβώς ένα πλεονέκτημα του PSR-4. Όποιος χρησιμοποιεί στην παραγωγή μια βελτιστοποιημένη λίστα κλάσεων, πρέπει να τη δημιουργεί εκ νέου σε κάθε παράδοση.

Πηγές

Άμεση επικοινωνία

Κάθε ώρα μετράει. Γράψτε μας τώρα.

Περιγράψτε σύντομα το σύστημα, την έκδοση PHP και ό,τι παρατηρείτε. Θα επικοινωνήσουμε μαζί σας, θα διευκρινίσουμε την κατάσταση και θα εργαστούμε εξ αποστάσεως μέχρι το περιστατικό να κλείσει και να τεκμηριωθεί.

Άμεση βοήθεια