Seit PHP5.1 können Programmierer auf die __autoload Funktion in PHP zurückgreifen. Diese Funktion erleichtert dem Programmierer vorallem bei großen Projekten die Arbeit. Die __autoload Funktion wird automatisch aufgerufen, wenn im PHP Quelltext eine eigene Klasse verwendet wird. Sinn und Zweck dieser Funktion ist entsprechend, dass benötigte Klassen automatisch eingebunden werden müssen und die jeweilige Datei nicht händisch eingebunden werden muss. In diesem Artikel möchte ich euch näher erläutern mit welchen Konzepten man die __autoload Funktion in euer Projekt einbinden könnt. Der Eintrag ist für fortgeschrittene Programmierer ausgelegt.
Einfacher Aufbau (nicht empfehlenswert!)
Als erstes Konzept möchte ich euch die einfachste Umsetzungsmöglichkeit vom Autoloader zeigen. Bei diesem Konzept muss der Array mit der Information in welcher Datei welche Klasse abgelegt ist ständig händisch erweitert werden. Bei einem kleinen Projekt mag das noch machbar sein, jedoch kann man bei kleinen Projekten auch einfach ein include / require_once machen. Dieses Beispiel soll also erstmal nur den grundlegenden Aufbau von __autoload veranschaulichen und stellt keine gute Lösung dar.
Die __autoload Funktion
Alles anzeigen
"classes"-Ordner
Diese Version arbeitet automatisch und die Funktion muss nicht erweitert werden. Bei kleineren Projekten kann diese Version durchaus noch effektiv genutzt werden, sobald die Anzahl der eigenen Klassen jedoch recht groß wird, ist dieses Konzept unübersichtlich.
Bei dieser Umsetzung ist es wichtig, dass jede Klasse sich in einer eigenen PHP-Datei befindet und der Dateiname muss mit dem Klassennamen (vorallem Groß- und Kleinschreibung) identisch sein. Die Dateiendung ist in diesem Fall .class.php und diese Dateien müssen im Ordner "classes" abgelegt werden.
Beispiele:
Klasse: Database
Dateiname: Database.class.php
Beispielhafter Inhalt der Datei Database.class.php
Alles anzeigen
Die __autoload Funtkion
Namensräume und __autoload()
Auch die seit PHP 5.3 verfügbaren Namensräume können in Verbindung mit __autoload() genutzt werden, da immer der vollqualifizierte Klassenname übergeben wird. Das heißt, dass, wenn ein Objekt der Klasse \kernel\configuration\ConfigurationManager erzeugt wird, immer dieser Name übergeben wird - auch wenn die Klasse z.B. in einen Namensraum importiert wurde und über einen anderen Namen angesprochen wird.
Sofern die Namensräume der Struktur der Dateien (in der die Klassen enthalten sind) entsprechen, können die Klassen aus verschiedenen Verzeichnissen geladen werden. Für die Verständlichkeit folgt ein Beispiel.
kernel/configuration/ConfigurationManager.php
kernel/registry/Registry.php
bootstrap.php
Alles anzeigen
Komplexer Lösungsansatz
Der zweite Lösungsansatz arbeitet ohne weitern Aufwand, aber wie ihr sicherlich schon festgesetllt habt, gibt es ein ziemlich großes Chaos, wenn viele Klassen hat, da diese nicht in einzelne Unterordner abgespeichert werden können. Das bedeutet, dass wir eine größere Ordnerstruktur auslesen müssen und für die Performance ist es in diesem Fall auch sehr wichtig, dass die Ordnerstruktur nicht bei jedem Aufruf von autoload durchforstet werden muss.
PHP bietet für die komplxere Verwendung auch die Möglichkeit eine Autoload-Klasse anstatt einer einfachen Funktion zu verwenden. Dazu muss jedoch mit dem Befehl spl_autoload_reigster definiert werden welche Klasse und welche darin enthaltene statische Methode die Autoload Funktion darstellt. In meinem Beispiel verwende ich dazu die Klasse Autoload und die statische Methode get.
Wie beim vorherigen Konzept muss wieder jede Klasse in einer eigenen Datei sein und der Dateiname muss entsprechend vom Klassennamen gewählt werden. Beispiel: Die Klasse Template befindet sich in der Datei Template.class.php
Die Autoload-Klasse
Alles anzeigen
Ich hoffe ich konnte euch mit diesem Eintrag behilflich sein und bei Fragen könnt ihr hier im Forum gerne ein neues Thema erstellen - es gibt genug Experten, die euch weiter helfen können
Einfacher Aufbau (nicht empfehlenswert!)
Als erstes Konzept möchte ich euch die einfachste Umsetzungsmöglichkeit vom Autoloader zeigen. Bei diesem Konzept muss der Array mit der Information in welcher Datei welche Klasse abgelegt ist ständig händisch erweitert werden. Bei einem kleinen Projekt mag das noch machbar sein, jedoch kann man bei kleinen Projekten auch einfach ein include / require_once machen. Dieses Beispiel soll also erstmal nur den grundlegenden Aufbau von __autoload veranschaulichen und stellt keine gute Lösung dar.
Die __autoload Funktion
Quellcode
- /**
- * __autoload will be called automatically if requiered class isn't included yet
- *
- * @param string $class name of requiered class
- */
- function __autoload($class) {
- $classes = array();
- $classes['Database'] = "include/db/Database.class.php";
- $classes['Template'] = "include/db/Template.class.php";
- if(isset($classes[$class])) {
- require_once $classes[$class];
- }
- }
"classes"-Ordner
Diese Version arbeitet automatisch und die Funktion muss nicht erweitert werden. Bei kleineren Projekten kann diese Version durchaus noch effektiv genutzt werden, sobald die Anzahl der eigenen Klassen jedoch recht groß wird, ist dieses Konzept unübersichtlich.
Bei dieser Umsetzung ist es wichtig, dass jede Klasse sich in einer eigenen PHP-Datei befindet und der Dateiname muss mit dem Klassennamen (vorallem Groß- und Kleinschreibung) identisch sein. Die Dateiendung ist in diesem Fall .class.php und diese Dateien müssen im Ordner "classes" abgelegt werden.
Beispiele:
Klasse: Database
Dateiname: Database.class.php
Beispielhafter Inhalt der Datei Database.class.php
Quellcode
- class Database {
- /**
- * constructor
- * open new database connection with given dbms
- *
- * @param string $dbms database management system
- * @param string $host host of dbms
- * @param string $user username for database conneciton
- * @param string $pass password for given user
- * @param string $db automatically selected database
- */
- public function __construct($dbms, $host, $user, $pass, $db) { }
- }
Die __autoload Funtkion
Namensräume und __autoload()
Auch die seit PHP 5.3 verfügbaren Namensräume können in Verbindung mit __autoload() genutzt werden, da immer der vollqualifizierte Klassenname übergeben wird. Das heißt, dass, wenn ein Objekt der Klasse \kernel\configuration\ConfigurationManager erzeugt wird, immer dieser Name übergeben wird - auch wenn die Klasse z.B. in einen Namensraum importiert wurde und über einen anderen Namen angesprochen wird.
Sofern die Namensräume der Struktur der Dateien (in der die Klassen enthalten sind) entsprechen, können die Klassen aus verschiedenen Verzeichnissen geladen werden. Für die Verständlichkeit folgt ein Beispiel.
kernel/configuration/ConfigurationManager.php
kernel/registry/Registry.php
bootstrap.php
Quellcode
- function __autoload($class) {
- // für Linux: \ in / umwandeln und die Dateiendung anhängen
- $class = str_replace('\\', '/', $class).'.php';
- if(!file_exists($class)) {
- throw new Exception('...', E_USER_ERROR);
- }
- include $class;
- }
- $configMgr = new kernel\configuration\ConfigurationManager();
- $registry = new kernel\registry\Registry();
Komplexer Lösungsansatz
Der zweite Lösungsansatz arbeitet ohne weitern Aufwand, aber wie ihr sicherlich schon festgesetllt habt, gibt es ein ziemlich großes Chaos, wenn viele Klassen hat, da diese nicht in einzelne Unterordner abgespeichert werden können. Das bedeutet, dass wir eine größere Ordnerstruktur auslesen müssen und für die Performance ist es in diesem Fall auch sehr wichtig, dass die Ordnerstruktur nicht bei jedem Aufruf von autoload durchforstet werden muss.
PHP bietet für die komplxere Verwendung auch die Möglichkeit eine Autoload-Klasse anstatt einer einfachen Funktion zu verwenden. Dazu muss jedoch mit dem Befehl spl_autoload_reigster definiert werden welche Klasse und welche darin enthaltene statische Methode die Autoload Funktion darstellt. In meinem Beispiel verwende ich dazu die Klasse Autoload und die statische Methode get.
Wie beim vorherigen Konzept muss wieder jede Klasse in einer eigenen Datei sein und der Dateiname muss entsprechend vom Klassennamen gewählt werden. Beispiel: Die Klasse Template befindet sich in der Datei Template.class.php
Die Autoload-Klasse
Quellcode
- abstract class Autoload {
- /**
- * file paths of classes
- *
- * @var array $files
- */
- private static $files;
- /**
- * cache file
- *
- * @var string $cache
- */
- private static $cache = "Autoload.cache.php";
- /**
- * import cached file array
- *
- */
- private static function init() {
- if(file_exists(self::$ache)) {
- self::$files = unserialize(file_get_contents(self::$cache));
- }
- else self::$files = array();
- }
- /**
- * include given class
- *
- * @param string $class name of requiered class
- * @param bool $firsttime[optional] first call for given class
- */
- public static function get($class, $firstime=true) {
- // load cache into local variable
- if(!is_array(self::$files)) self::init();
- if(isset(self::$files[$class])) {
- require_once self::$files[$class];
- return;
- }
- if($firsttime) {
- $files = self::buildCache();
- file_put_contents(self::$cache, serialize($files));
- self::get($class, false);
- return;
- }
- // here you could throw an exception or output other errors if you want
- }
- /**
- * read filesystem recursive and build class array
- *
- * @param string $directory[optional]
- * @return array
- */
- private static function buildCache($directory='.') {
- $files = array();
- $dir = dir($directory);
- while($item = $dir->read()) {
- if($item == '.' || $item == "..") {
- continue;
- }
- if(is_directory($item)) {
- $found = self::buildCache($directory.DIRECTORY_SEPARATOR.$item);
- $files = array_merge($files, $found);
- }
- if(is_file($item) && preg_match("#(.+)\.class\.php#", $item, $match) {
- $class = $match[1];
- $files[$class] = $directory.DIRECTORY_SEPARATOR.$item;
- }
- }
- return $files;
- }
- }
Ich hoffe ich konnte euch mit diesem Eintrag behilflich sein und bei Fragen könnt ihr hier im Forum gerne ein neues Thema erstellen - es gibt genug Experten, die euch weiter helfen können
10.736 mal gelesen