Sven Rautenberg: spl_autoload_register

Beitrag lesen

Moin!

Hallo werte Freunde,

ich probiere mich gerade wieder mit Klassen und hab hier ein schönes Autoload gefunden. Gibt es einen Grund, warum

spl_autoload_register()

include verwendet, statt bspw. include_once, oder gar require_once?

http://php.net/manual/de/function.spl-autoload-register.php#example-4337

Der Beispielcode:

spl_autoload_register(function ($class) {
    include 'classes/' . $class . '.class.php';
});

Ja, es gibt zwei Gründe.

  1. _once-Funktionen müssen intern Buch führen über die bereits geladenen Dateien. Das kostet Performance, weil vor allem relative Pfade erst einmal zu vollständigen, absoluten Pfaden im Dateisystem expandiert werden müssen. Du provozierst also eventuell Dateisystemzugriffe, auch wenn "once" letztendlich dann feststellen würde, dass die Datei bereits eingebunden war.
    Weiterhin ist das PHP-Autoloading so gestrickt, dass die Autoload-Funktion, die ausschließlich den Code einer benötigten Klasse laden soll, eben nur genau dann aufgerufen wird, wenn diese Klasse, Interface oder Trait noch nicht bekannt ist. Kennt das laufende PHP-Skript hingegen die Klasse schon, wird die Autoload-Funktion nicht aufgerufen. Aus diesem Grund muss man nicht mittels _once verhindern, dass ein Skript, welches bereits eingebunden war und eine Klasse definiert, erneut eingebunden wird und die Klasse ein zweites Mal definiert - was mit einem Fehler enden würde.
  2. Der Grund, warum hier "include" und nicht "require" benutzt wird, liegt daran, dass PHP erlaubt, mehr als eine Autoload-Funktion zu registrieren. Sofern man beim Registrieren einer Funktion nichts anderes angibt, wird die hinzugefügte Funktion immer ans Ende der Liste aller registrierten Funktionen gehängt.
    Wenn eine Klasse geladen werden soll, wird die erste Autoload-Funktion aufgerufen. Sie soll die Klasse laden. Gelingt das jedoch nicht, sollte die nächste Autoload-Funktion es versuchen. Das klappt aber nur, wenn die erste Funktion keinen Fehler erzeugt und das Skript abbricht. "require" bricht aber ab, wenn die gewünschte Datei nicht existiert - include lässt das Skript weiterlaufen.

Du hast es hier also mit zwei relevanten Effekten zu tun: Erstens braucht es die Buchführung für bereits eingebundene Dateien nicht, und zweitens darf die Autoload-Funktion nicht abbrechen, wenn die Klasse nicht geladen werden kann.

Autoloading ist übrigens schon uralt, Christian Seiler hat Ende 2007 dazu was ins Blog geschrieben: https://blog.selfhtml.org/2007/12/04/php-autoload/

Die dort erwähnte Funktion "__autoload" sollte man unbedingt vermeiden - sie ist unhandlich und inkompatibel zu vielen Bibliotheken, die ihrerseits Autoloading machen.

Außerdem sei dir an dieser Stelle wärmstens ans Herz gelegt, dich mal über "Composer" zu informieren.

Autoloading an sich ist eine relativ langweilige Sache, aber insbesondere nervig, wenn jeder Entwickler sein eigenes Dateinamensschema erfindet, und seinen eigenen Autoloader schreibt. Deshalb haben alle wichtigen PHP-Projekte sich zur PHP-FIG zusammengeschlossen und einige Standards verabredet, an die sie sich halten wollen, um Code zueinander kompatibel zu machen. Für Autoloading sind die zwei Standards "PSR-0" und "PSR-4" entstanden, und Composer erlaubt es auf sehr einfache Art, für eigenen Code das Autoloading zu definieren - was insbesondere vorteilhaft ist, wenn man noch fremde Bibliotheken mit einbindet.

(Anmerkung: PSR-0 ist deprecated und nur noch relevant für Projekte, die keine Namespaces für ihre Klassen verwenden. Das ist typischerweise der Fall, wenn sie zu PHP 5.2 und älter kompatibel sein wollen/müssen, und bedeutet, dass uralte PHP-Versionen ohne Security-Fixes benutzt werden - bloß weg damit!)

Grüße Sven