PHP Autoloader

von Marco Simbürger

Autoloading ist der Prozess des automatischen Ladens von PHP-Klassen, ohne die Klassen-Dateien explizit mit einer Funktionen, wie require(), require_once(), include() oder include_once() zu laden.

In der professionellen Programmierung mit PHP ist die Objektorientierung nicht mehr wegzudenken. In grossen Projekten mit einer Vielzahl an Klassen sollte eine passende Struktur und ein Autoloader angelegt werden, um die Klassen automatisiert zu laden.

Hinweis: Grundsätzlich verwendet man heutzutage Frameworks, wie zum Beispiel Symfony oder Laravel, die zusammen mit Composer umfangreiche Autoloading-Funktionalitäten resp. Möglichkeiten zum einfachen Instanziieren von Klassen mit sich bringen. Fürs Verständnis bauen wir uns die Autoloader in diesem Blogpost selbst.

Wie man es vor dem Autoloader-Zeitalter gemacht hat:

<?php

// Klassen-Dateien importieren.
require_once('MyClass.php');
require_once('MyOtherClass.php');

// Klassen verwenden.
$object1 = new MyClass();
$object2 = new MyOtherClass();

Die __autoload() Methode

__autoload() ist eine Magic-Methode und wird automatisch von PHP aufgerufen, wenn eine Klasse zum ersten mal instanziiert wird.

Der Klassenname der gewünschten Klasse wird der __autoload() Methode als Parameter übergeben.

Im diesem Beispiel wird die Datei (classes/MyClass.php) durch die __autoload() Methode automatisch importiert, wenn die MyClass Klasse instanziiert wird. Für den Pfad wird vom Speicherort der ausführenden PHP-Datei ausgegangen.

/index.php

<?php

function __autoload($className) {
  require_once('classes/' . $className . '.php');
}

// Durch die __autoload() Methode, wird die
// Klassen-Datei /classes/MyClass.php aufgerufen.
$object = new MyClass();

Mehrere Autoloader mit spl_autoload_register()

Ab PHP 7.2.0 ist die Funktion __autoload()veraltet. Man sollte stattdessen spl_autoload_register() verwenden.

Hinweis: Die Standard PHP Library (SPL) ist eine in PHP eingebaute Bibliothek. Für mehr Informationen siehe: Standard PHP Library (SPL)

Mit spl_autoload_register() ist es möglich mehrere Autoloader zu registrieren. Hat ein Autoloader eine Klasse nicht gefunden, wird der nächste Autoloader aufgerufen. Dieses Prinzip ist vor allem bei Frameworks anzutreffen, denn diese haben in der Regel eine eigene Verzeichnisstruktur. Der Autoloader, der zuerst registriert wird, wird als erstes aufgerufen.

Im nachfolgenden Beispiel wird die Klasse MyViewClass vom ersten Autoloader nicht im "model" Ordner gefunden, dafür vom zweiten Autoloader im Ordner "views".

/index.php

<?php

function myModelAutoloader($className) {
  require_once('/models/' . $className .'.php');
}

function myViewAutoloader($className) {
  require_once('/views/' . $className .'.php');
}

spl_autoload_register('myModelAutoloader');
spl_autoload_register('myViewAutoloader');

// /models/MyModelClass.php
$model = new MyModelClass();

// /views/MyViewClass.php
$view = new MyViewClass();

Autoloader mit Namespaces

Mit spl_autoload_register() können auch Namespaces verwendet werden. Die PHP-Klassen können ohne require oder include automatisch geladen werden. Dafür verwendet man spl_autoload_register() ohne Callback-Parameter. Dadurch wird erreicht, dass die Standard-Implementierung von spl_autoload() verwendet wird.

In diesem Beispiel findet spl_autoload_register() die Klassen-Dateien, da der Namespace mit der Ordnerstruktur übereinstimmt.

Dateistruktur

|- MyNameSpace
   |- TestNamespace1.php
   |- TestNamespace2.php
|- index.php

/MyNameSpace/TestNamespace1.php

<?php

namespace MyNameSpace;

class TestNamespace1 {

  public function get(){
    return __CLASS__;
  }

}

/MyNameSpace/TestNamespace2.php

<?php

namespace MyNameSpace;

class TestNamespace2 {

  public function get(){
    return __CLASS__;
  }

}

/index.php

<?php

spl_autoload_register();

$test = new MyNameSpace\TestNamespace1();
echo $test->get();
echo '<br>';
$test2 = new MyNameSpace\TestNamespace2();
echo $test2->get();

Ausgabe

MyNameSpace\TestNamespace1
MyNameSpace\TestNamespace2

Autoloader mit PSR-0

Die PHP Standard Recommendation (PSR) ist eine PHP-Spezifikation, die von der PHP Framework Interop Group veröffentlicht wurde. Sie dient der Standardisierung von Programmierkonzepten in PHP. Ziel ist es, die Interoperabilität (Fähigkeit zur Zusammenarbeit) von Komponenten zu ermöglichen und eine gemeinsame technische Basis für die Implementierung von bewährten Konzepten für optimale Programmier- und Testpraktiken zu schaffen. Die PHP-FIG wurde von mehreren PHP-Framework-Gründern gebildet.

PSR-0 beschreibt die obligatorischen Anforderungen, die für die Interoperabilität für Autoloader eingehalten werden müssen. Siehe: PSR-0

Ein Beispiel dazu:

Dateistruktur

|- MarcoSimbuerger
    |- AutoloaderExample
        |- Controller
           |- Demo
               |- Test.php
|- index.php

/MarcoSimbuerger/AutoloaderExample/Controller/Demo/Test.php

<?php

namespace MarcoSimbuerger\AutoloaderExample\Controller\Demo;

class Test {

  public function get(){
    return __CLASS__;
  }

}

/index.php

<?php

function myAutoloader($className) {
  $className = ltrim($className, '\\');
  $fileName  = '';
  $namespace = '';
  if ($lastNsPos = strrpos($className, '\\')) {
    $namespace = substr($className, 0, $lastNsPos);
    $className = substr($className, $lastNsPos + 1);
    $fileName  = str_replace('\\', DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR;
  }
  $fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php';

  require $fileName;
}

spl_autoload_register('myAutoloader');

$test = new \MarcoSimbuerger\AutoloaderExample\Controller\Demo\Test();
echo $test->get();

Ausgabe

MarcoSimbuerger\AutoloaderExample\Controller\Demo\Test

Autoloader mit PSR-4

PSR-4 beschreibt eine Spezifikation fürs Autoloading von Klassen aus Dateipfaden. PSR-4 ist vollständig kompatibel und kann zusätzlich zu jeder anderen Autoloading-Spezifikation, einschliesslich PSR-0, verwendet werden. PSR-4 beschreibt zudem, wo Dateien zu platzieren sind, die gemäss der Spezifikation automatisch geladen werden.

Dateistruktur (Kopie)

|- src
  |- MarcoSimbuerger
      |- AutoloaderExample
          |- Controller
             |- Demo
                 |- Test.php
|- index.php

/src/MarcoSimbuerger/AutoloaderExample/Controller/Demo/Test.php

<?php

namespace Autoloader\Examples\MarcoSimbuerger\AutoloaderExample\Controller\Demo;

class Test {

  public function get(){
    return __CLASS__;
  }

}

/index.php

<?php

function myAutoloader($className) {

  // Projekt spezifischer Namespace-Prefix.
  $prefix = 'Autoloader\\Examples\\';

  // Base-Directory für den Namespace-Prefix.
  $baseDir = __DIR__ . '/src/';

  // Check, ob die Klasse den Namespace-Prefix verwendet.
  $len = strlen($prefix);
  if (strncmp($prefix, $className, $len) !== 0) {
    // Wenn der Namespace-Prefix nicht verwendet wird, wird abgebrochen.
    return;
  }

  // Den relativen Klassennamen ermitteln.
  $relativeClassName = substr($className, $len);

  // Den Namespace-Präfix mit dem Base-Directory ergänzen,
  // Namespace-Trennzeichen durch Verzeichnis-Trennzeichen im relativen Klassennamen ersetzen,
  // .php anhängen.
  $file = $baseDir . str_replace('\\', '/', $relativeClassName) . '.php';

  // Pfad zur Klassen-Datei zurückgeben.
  if (file_exists($file)) {
    require $file;
  }
}

spl_autoload_register('myAutoloader');

$test = new \Autoloader\Examples\MarcoSimbuerger\AutoloaderExample\Controller\Demo\Test();
echo $test->get();

Ausgabe

Autoloader\Examples\MarcoSimbuerger\AutoloaderExample\Controller\Demo\Test

Autoloading mit Composer

Alle Infos bzgl. Autoloading mit Composer sind hier zu finden: Composer verstehen - Teil 5 - Autoloading

Zurück

Kommentare

Einen Kommentar schreiben

Bitte rechnen Sie 3 plus 8.