PHP – Automatisches Laden von Klassen (autoloading)

Nachdem ihr bereits wisst wie ihr Klassen definiert und sie in verschiedenen Namensräumen unterbringt, beschäftigt sich dieser Artikel damit die Klassen möglichst effizient bekannt zu machen – das heißt ohne jedes mal ein require im Code zu benutzen. Das Konzept dahinter heißt Autoloading.


Das Beispiel

Im Rahmen dieses Beitrags werde ich folgende Klasse verwenden.

Sie befindet sich in der Datei Person.php im Ordner Example.


Wozu benötige ich Autoloading?

Bevor wir eine Klasse in PHP verwenden können, muss sie definiert werden. Dies findet in einer separaten Datei statt und diese Datei muss von uns somit eingebunden werden. Bisher benötigen wir dazu jedes mal ein require.

Das wird insbesondere dann schwierig, wenn unsere Klassen wiederum andere Klassen verwenden. Schreiben wir überall ein require nehmen wir uns sehr viel Flexibilität für spätere Änderungen.

Wir könnten natürlich global (zum Beispiel in der index.php) eine Liste aller Klassen hinterlegen. Das wäre allerdings sehr ineffizient, weil jetzt bei jedem Programmaufruf, alle Dateien geladen werden müssen, obwohl wir nur einen Bruchteil davon benutzen werden.

Noch schlimmer wird es, wenn wir Bibliotheken von Drittanbietern verwenden wollen. Da kennen wir die Ordnerstruktur überhaupt nicht.

Dieses Problem können wir sehr elegant mit Autoloading lösen.


Verfügbare Funktionen

PHP bietet zwei Möglichkeiten mit Autoloading umzugehen. Zum einen __autoload() und zum anderen spl_autoload_register().

__autoload()

Wie andere magische Methoden auch, wird sie von uns definiert und PHP erkennt anhand des Namens, was wir damit bezwecken wollen. Sie wird immer dann aufgerufen, wenn wir noch unbekannte Klassen, Interfaces oder Traits verwenden. Als Parameter erhalten wir den Namen.

An dieser Stelle werden wir jetzt dafür belohnt, dass wir uns bei der Benennung unserer Namensräume und Klassen an ein einheitliches Schema gehalten haben. Wir müssen lediglich die Trennzeichen für Namensräume durch das Trennzeichen für Verzeichnisse ersetzen und ein .php ergänzen.

Wie alle Funktionen können wir auch __autoload() nur ein einziges Mal definieren. Wir können also in unserem Programm nur diesen einen Autoloader haben. Das wird spätestens dann zum Problem, wenn wir Bibliotheken von Drittanbietern verwenden. Wir müssten deren Ordnerstruktur in unseren Autoloader aufnehmen.

Aufgrund dieser Nachteile wird von der Verwendung abgeraten!

spl_autoload_register()

Im Gegensatz zu __autoload() ist spl_autoload_register() eine PHP-Funktion, die wir nur verwenden und nicht definieren. Eine Bibliothek kann sie also unabhängig von uns aufrufen und einen Autoloader registrieren. Genauso können wir jetzt für jedes unserer Module einen eigenen Autoloader anmelden.

Sie benötigt als Parameter ein callable, also eine Funktion, die zunächst genauso aussieht wie unsere __autoload() oben.

Stößt PHP jetzt auf eine unbekannte Klasse werden alle registrierten Autoloader der Reihe nach durchlaufen, bis einer die notwendige Datei einbindet, oder keine weiteren Autoloader mehr vorhanden sind.

Daher ist es äußerst wichtig, dass sich jede so registrierte Funktion nur um „ihre“ Klassen kümmert und für den Rest keine Fehler erzeugt. Die Prüfung auf file_exists hilft uns dabei. So ist sicher gestellt, dass spätere Autoloader ebenfalls einen Versuch bekommen und PHP nicht aufgrund der fehlenden Datei einen Fatal Error wirft.


Autoloader Klasse

Moderne Frameworks bringen gleich ganze Klassen mit, die als Autoloader dienen. Dies wird dadurch ermöglicht, dass spl_autoload_register() als Parameter nicht nur eine Funktion sondern auch ein Array aus Objekt und Funktion akzeptiert.

Aber Achtung: Unsere Autoloader Klasse kann sich nicht selbst laden, wenn wir sie in einer eigenen Datei definieren. Diese müssen wir also vor ihrer Verwendung über require bekannt machen.

Beispiel einer Autoloader Klasse

Wir bieten dem Anwender die Möglichkeit für verschiedene Namensräume unterschiedliche Ordner zu definieren. Durch das Fluent Interface lassen sich Autoloader jetzt schön lesbar anmelden.

Mit dieser Klasse haben wir einen PSR-0 Autoloader für den zwingend Namensräume verwendet werden müssen. Als kleine Übungsaufgabe solltet ihr ihn PSR-4 kompatibel machen, denn das ist der Standard, der heute verwendet werden sollte.


 

Hier findest du weitere Tutorials.