Autoloading mittels PHP Namespaces
von Thomas Müller
Seit Version 5.3 unterstützt PHP (endlich) Namespaces. Autoloading ist auch nichts neues mehr – Wird eine Klasse zur Laufzeit nicht gefunden, wird versucht die Klasse mittels der __autoload() Funktion zu laden, bevor ein PHP Fehler erscheint.
Setzt man Klassen ein, die Namespaces nutzen, wird der Namespace der Funktion übergeben. Benutzt man für sein Script eine Ordnerstruktur, die den Namespaces entspricht, ist es einfach aus dem Namespace heraus auf den Ordner in dem die Klasse liegt zu schließen.
Hier ein Beispiel:
function __autoload($className) { // Die Backslashes des Namespaces zu Slashes umwandeln $fileName = str_replace("\\", "/", $className).".php"; if (file_exists($fileName)) { require_once $fileName; } }
Natürlich setzt dieses Beispiel voraus, dass der Dateiname dem Klassennamen entspricht. Diese Konventionen sind in anderen Sprachen üblich. Noch einfacher geht es jedoch mittels der neuen SPL Funktionen. Dadurch reicht der folgende Aufruf:
spl_autoload_extensions(".php"); spl_autoload_register();
Die Funktionalität ist dieselbe, wie in der zuvor vorgestellten __autoload() Funktion, jedoch schneller, wie man einem Kommentar im PHP Manual entnehmen kann.
Ein Beispiel
Datei: \com\my\app\foo\Foo.php
namespace com\my\app\foo; class Foo { }
Datei: \com\my\app\bar\Bar.php
namespace com\my\app\bar; class Bar { }
Datei /index.php
use \com\my\app\bar as Bar; spl_autoload_extensions(".php"); spl_autoload_register(); $foo = new \com\my\app\foo\Foo(); $bar = new Bar\Bar();
Wie dieses kleine Beispiel zeigt, funktioniert das Autoloading auch, wenn Namespace-Aliase eingesetzt werden.
Kommentare
Dieses Beispiel erzeugt folgenden Fehler:
Parse error: syntax error, unexpected ‘/’, expecting T_STRING or T_NS_SEPARATOR in D:\Projects\Test\index.php on line 2
Wenn ich das ‘/’ entferne bekomme ich folgenden Fehler:
Warning: The use statement with non-compound name ‘com’ has no effect in D:\Projects\Test\index.php on line 2
Parse error: syntax error, unexpected ‘/’, expecting ‘,’ or ‘;’ in D:\Projects\Test\index.php on line 2
D:\Projects\Test>php -v
PHP 5.3.0 (cli) (built: Jul 2 2009 21:08:11)
Copyright (c) 1997-2009 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2009 Zend Technologies
with Xdebug v2.0.5, Copyright (c) 2002-2008, by Derick Rethans
Es müssen natürlich Backslashes sein. Warum es hier Slashes sind, kann ich mir jetzt auch nicht mehr erklären :)
Vielen Dank für diesen hilfreichen Eintrag :)
Bei mir funktioniert das auf einem Windows-Server wunderbar, jedoch leider unter (Debian-)Linux nicht. Ich habe schon stundenlang gegooglet, aber nicht was wirklich passendes gefunden. Alle meine Dateinamen, Ordnernamen und Klassennamen habe ich (zum Testen) klein geschrieben, um Probleme zu umschiffen. Ist aber nichts zu machen.
Hat jemand vielleicht eine Idee? Wäre echt dankbar ;)
Liebe Grüße
Björn
PS: Falls mehr Input benötigt wird, gebt Bescheid.
Das Problem (welches übrigends alle U*ix basierten Systeme betrifft) das Björn geschildert hat, ist nach wie vor existent und ist ein Bug in der spl_autoload implementation in PHP. Es gibt auch schon einen Bugfix dafür, aber auf diesen müssen wir noch so lange warten bis PHP 5.3.3 released ist oder man nimmt eine Snapshot-Version von snaps.php.net.
Alternativ funktioniert aber auch der workaround der unter der nachfolgenden URL beschrieben ist.
http://stackoverflow.com/questions/2862133/namespace-autoload-works-under-windows-but-not-on-linux