PHP Autoload

Autoloading bezeichnet einen Mechanismus der selbstständig dafür sorgt, dass bestimmte Teile eines Programms automatisch eingelesen werden sobald sie benötigt werden. In PHP gibt es dafür einige Implementierungen in der Standard Library. Die geeignetste davon ist die Funktion

bool spl_autoload_register ([ callable $callback [, bool $throw = true [, bool $prepend = false ]]] ).

In dem Moment in dem eine Klasse (auch ein Interface oder Trait) referenziert wird die noch nicht bekannt ist, werden alle über diese Funktion registrierten Callbacks (sprich: »Autoloader«) der Reihe nach aufgerufen. Der Name der Klasse wird als Parameter an den Autoloader übergeben (bzw. der Name des Interfaces oder des Traits).

Dem Autoloader fällt die Aufgabe zu, zu dem gegebenen Namen die passende Datei zu finden und diese zu laden. Um das zu bewerkstelligen könnte man beispielsweise eine Liste aller Klassen und ihrer dazugehörigen Dateien pflegen:

<?php
// autoload.php

namespace MyProject;

/**
 * @param string $className
 * @return bool (Whether the class is known or not)
 */
function myAutoloader( $className ) {

	$classMap = [
		'MyProject\\MyClass'           
			=> '/var/www/my-project/includes/MyClass.php',
		'Your_Project\\Your_Interface' 
			=> '/var/www/your-project/php/Your_Interface.php';
		'MyProject\\OurTrait'          
			=> '/var/www/my-project/includes/OurTrait.trait.php'
	];

	if ( isset( $classMap[ $class ] ) ) {
	
		require_once $classMap[ $class ];
		return TRUE;
	}
	
	return FALSE;
}
<?php
// index.php

namespace MyProject;

require_once 'autoload.php';
spl_autoload_register( __NAMESPACE__ . '\\myAutoloader' );

// here the file "/var/www/my-project/includes/MyClass.php" 
// gets loaded
$instance = new MyClass; 

Das Beispiel soll zwei Dinge verdeutlichen:

  1. Der Klassenname wird immer absolut übergeben, d.h. mit vollständigem Namespace.
  2. Wie die Dateien heißen und wo sie liegen ist völlig egal. Auch eine Prüfung, ob die Datei tatsächlich existiert ist nicht zwingend notwendig. (Es hilft sogar beim Debuggen des Autoloaders wenn man die Prüfung kurzzeitig auskommentiert. Im produktiven Einsatz sollte man auf die Existenz prüfen und ggf. FALSE zurück geben, dann können sich evtl. andere Autoloader darum kümmern.)

So eine Liste ist natürlich wenig hilfreich, da sie gepflegt werden will. Sinnvoller[1] ist es, sich ein Schema auszudenken, wonach absolute Klassennamen auf eine Verzeichnis- und Dateistruktur abgebildet werden. Solche Abbildungsregeln existieren bereits in Form von PSR-0 (veraltet) und PSR-4. Letztere beschreibt im Wesentlichen, dass jedes Namespace-Level auf ein Verzeichnis (innerhalb eines gemeinsamen Wurzelverzeichnisses) abgebildet wird und der Klassenname dem Dateinamen entspricht. Beispiel:

\MyProject\Core\MyApplication…/MyProject/Core/MyApplication.php

Implementierungen solcher Autoloader existieren reichlich. Natürlich habe ich mich auch an einer Implementierung versucht: Requisite. (Requisite verfolgt den Ansatz Mapping und das Loading voneinander zu trennen, basierend auf einer Idee von Tom Buttler.) Welcher Autoloader verwendet wird ist aber letztlich eine Geschmacksfrage. Man sollte sich für eine Variante entscheiden (oder selbst eine schreiben), gut testen und diese möglichst regelmäßig verwenden.

Um sich das Leben mit dem Autoloading etwas zu vereinfachen, hier ein paar Leitlinien:

  • Da das Prinzip in PHP im Wesentlichen für objektorientierte Programmierung entwickelt wurde, funktioniert es nicht für Funktionen. Diese müssen nach wie vor manuell geladen werden.
  • Folge der Konvention »Eine Klasse, eine Datei« (gilt auch für Interfaces und Traits). Das ist zwar nicht zwangsläufig notwendig, vereinfacht aber die Organisation des Codes und damit die Abbildungsregeln für Dateinamen.
  • Trenne deklarierenden von ausführendem Code! D.h. in einer Datei, in der eine Klasse deklariert wird, wird kein Code ausgeführt. (Das gilt gleichermaßen für Dateien, in denen Funktionen deklariert werden.) Andernfalls kommt es zu unschönen Begleiterscheinungen wenn der Code dann doch mal anderweitig Verwendung findet, als wofür er ursprünglich gedacht war. In Tests zum Beispiel.
  1. Sinnvoll im Sinne des Prinzips »Convention over Configuration«

Kommentare

Es wurden noch keine Kommentarte zu diesem Artikel geschrieben.

Fragen, Ideen oder Kritik? – Hier ist Platz dafür!

Dein Kommentar

Um ein Kommentar abzugeben, reicht der Text im Kommentarfeld. Die Angabe eines Namens wäre nett, ist aber nicht erforderlich.

Du darfst folgenden HTML-Code verwenden, musst aber nicht:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>