Was ist Autoloading? Wie benutzt man spl_autoload, __autoload und spl_autoload_register?

203

Ich lerne fortgeschrittene PHP-Standards und versuche, neue und nützliche Methoden zu implementieren. Früher habe ich __autoloadnur verwendet, um mit mehreren Dateien auf jeder Seite zu entkommen, aber kürzlich habe ich einen Tipp dazu gesehen__autoload manual

spl_autoload_register () bietet eine flexiblere Alternative zum automatischen Laden von Klassen. Aus diesem Grund wird von der Verwendung von __autoload () abgeraten und möglicherweise in Zukunft veraltet oder entfernt.

aber ich kann wirklich nicht herausfinden , wie zu implementieren spl_autoloadundspl_autoload_register

diEcho
quelle

Antworten:

334

spl_autoload_register() Mit dieser Option können Sie mehrere Funktionen (oder statische Methoden aus Ihrer eigenen Autoload-Klasse) registrieren, die PHP in einen Stapel / eine Warteschlange stellt und nacheinander aufruft, wenn eine "neue Klasse" deklariert wird.

Also zum Beispiel:

spl_autoload_register('myAutoloader');

function myAutoloader($className)
{
    $path = '/path/to/class/';

    include $path.$className.'.php';
}

//-------------------------------------

$myClass = new MyClass();

Im obigen Beispiel ist "MyClass" der Name der Klasse, die Sie instanziieren möchten. PHP übergibt diesen Namen als Zeichenfolge an spl_autoload_register(), sodass Sie die Variable abrufen und damit die entsprechende Klasse / Datei "einschließen" können . Infolgedessen müssen Sie diese Klasse nicht speziell über eine include / require-Anweisung einschließen ...

Rufen Sie einfach die Klasse auf, die Sie instanziieren möchten, wie im obigen Beispiel, und da Sie eine eigene Funktion (via spl_autoload_register()) registriert haben , die herausfindet, wo sich alle Ihre Klassen befinden, verwendet PHP diese Funktion.

Der Vorteil der Verwendung spl_autoload_register() besteht darin, dass __autoload()Sie nicht in jeder von Ihnen erstellten Datei eine Autoload-Funktion implementieren müssen. spl_autoload_register()Außerdem können Sie mehrere Autoload-Funktionen registrieren, um das Autoloading zu beschleunigen und es noch einfacher zu machen.

Beispiel:

spl_autoload_register('MyAutoloader::ClassLoader');
spl_autoload_register('MyAutoloader::LibraryLoader');
spl_autoload_register('MyAutoloader::HelperLoader');
spl_autoload_register('MyAutoloader::DatabaseLoader');

class MyAutoloader
{
    public static function ClassLoader($className)
    {
         //your loading logic here
    }


    public static function LibraryLoader($className)
    {
         //your loading logic here
    }

In Bezug auf spl_autoload heißt es im Handbuch:

Diese Funktion soll als Standardimplementierung für verwendet werden __autoload() . Wenn nichts anderes angegeben ist und spl_autoload_register()ohne Parameter aufgerufen wird, werden diese Funktionen für einen späteren Aufruf von verwendet __autoload().

Praktischer ausgedrückt: Wenn sich alle Ihre Dateien in einem einzigen Verzeichnis befinden und Ihre Anwendung nicht nur .php-Dateien, sondern auch benutzerdefinierte Konfigurationsdateien mit .inc-Erweiterungen verwendet, besteht eine Strategie darin, ein Verzeichnis hinzuzufügen, das alle enthält Dateien zu PHPs Include-Pfad (via set_include_path() ).
Und da Sie auch Ihre Konfigurationsdateien benötigen, würden Sie spl_autoload_extensions()die Erweiterungen auflisten, nach denen PHP suchen soll.

Beispiel:

set_include_path(get_include_path().PATH_SEPARATOR.'path/to/my/directory/');
spl_autoload_extensions('.php, .inc');
spl_autoload_register();

Da spl_autoload die Standardimplementierung der __autoload()Magic-Methode ist, ruft PHP spl_autoload auf, wenn Sie versuchen, eine neue Klasse zu instanziieren.

Hoffe das hilft...

Brownbay
quelle
35
Dies ist möglicherweise eine der besten Antworten in der Geschichte der Antworten aller Zeiten. Respekt. Ich hatte eines dieser "OMG! Jetzt macht alles Sinn!" Momente wegen dir, mein guter Mann. Ich denke, ich könnte einfach einen Fanclub gründen.
Just Plain High
2
Um dies zur besten Antwort aller Antworten zu machen, auch in alternativen Universen, fügen Sie bitte hinzu, dass spl_autoload sehr, ähm, "hilfreich" (?) Alle Dateinamen in Kleinbuchstaben konvertiert (siehe meinen Kommentar zu @user unten). Spl_autoload_register () Vanille kann nicht verwendet werden, wenn Ihnen CapitalLettersAndStuff gefällt.
Just Plain High
6
@ Just Plain High Ich habe dieses Problem nicht und alle meine Klassendateien sind mit einem Kamel versehen. Übrigens ist dies eine wunderbare Antwort. Es hat mir geholfen, mich mit einem einfachen Konzept vertraut zu machen, das ich erst verstehen konnte, als ich diesen Beitrag gelesen habe! Meine 85 (und wachsende) Zeile enthält eine Datei, die alle meine Klassendateien enthält. Sie enthält jetzt 7 Zeilen!
Kyle
2
Dies ist in der Tat eine gute Antwort, aber mir fehlt eine Sache. Was ist die eigentliche Standardfunktionalität? Bei mir bekannten Klassen wird der Namespace als Pfad und der Klassenname als Dateiname verwendet. Obwohl ich nicht herausfinden kann, wie es mit Funktionen funktioniert.
SiXoS
2
Ist nicht einer der großen Vorteile bei der Verwendung spl_autoload_register()(und __autoload()im Allgemeinen), dass das verzögerte Laden Dateien / Klassen umfasst? Dies wird durch die Antwort impliziert, aber nicht explizit angegeben. Für mich sind dies wichtige Informationen, die sich perfekt für Ihre Antwort eignen! :)
Rinogo
13

Seit PHP 5.3 können Sie spl_autoload_register()mit Namespaces arbeiten, was bedeutet, dass Sie Ihr Projekt organisieren und Ihre PHP-Klassen automatisch laden können, ohne dass dies erforderlich oder eingeschlossen ist und ohne eine neu zu definieren__autoload() Funktion Funktion neu zu definieren.

Um dieses Verhalten zu demonstrieren, erstellen Sie einfach eine Datei mit dem Namen index.php:

<?php
spl_autoload_register();
var_dump(new Main\Application);

Erstellen Sie dann einen Ordner mit dem Namen Main direkt neben der Datei index.php. Erstellen Sie schließlich eine Datei mit dem Namen Application.php in Main und fügen Sie den folgenden Code ein:

<?php namespace Main;
class Application{}
user1974206
quelle
9
Ein Hinweis aus meiner Fummelei mit all dem: spl_autoload () - und damit spl_autoload_register () - konvertiert Dateinamen in Kleinbuchstaben (trotz Fehlerberichten, Bitten und wütenden Abstimmungen). Dies bedeutet, dass Sie möglicherweise nach "Main \ Application" suchen, spl_autoload jedoch nach "main \ application". Wenn Sie Kamele mögen, wie ich, müssen Sie Ihre eigene Funktion schreiben. Es gibt ein schönes Starter-Beispiel hier: github.com/ircmaxell/PHP-CryptLib/blob/…
Just Plain High
1
Vorteile: spl_autoload_register () ist die schnellste Methode zum automatischen Laden. Nachteile: Es funktioniert nur mit Dateien / Klassen in Kleinbuchstaben und auch mit Namespaces, die heutzutage nur sehr viel Zeit haben (keine Option, CamelCase usw. zu verwenden). Wenn Sie jedoch mit der Struktur namespace / classname.php leben können, suchen Sie nicht weiter.
Stamster
1
spl_autoload_register()Die Standardimplementierung kann geerbte Klassen nicht finden. Wenn Sie also Standardeinstellungen, Kleinbuchstaben und Verzeichnisse verwenden, die den Namespace-Pfad widerspiegeln, funktioniert alles einwandfrei, es sei denn, ich habe eine Klasse, die eine andere Klasse (übergeordnet) erweitert. PHP gibt dann den Fehler aus, dass es diese übergeordnete Klasse nicht finden kann, selbst wenn sie sich alle im selben Verzeichnis / Namespace befinden! Was verwirrend ist, ist, dass buchstäblich nur Klassen der ersten Ebene gefunden werden, so dass ich spl_autoload_register()kurz nach der ersten eine andere mit anonymer Funktionsregel einfügen musste, um fehlende übergeordnete / geerbte Klassen manuell einzuschließen.
Stamster
1

Hier ist die Art und Weise, wie ich Autoload verwende. Im angegebenen Beispiel möchte ich Klassen aus 3 verschiedenen Verzeichnissen laden.

function namespaceAutoload($rawClass){

$class = str_replace('\\', DIRECTORY_SEPARATOR, $rawClass);

$possiblePaths[] = '..\sys\class\file.php';
$possiblePaths[] = '..\sys\class\lib\file.php';
$possiblePaths[] = '..\sys\class\class.file.inc.php';

foreach ($possiblePaths as $templatePath) {
    $path = str_replace(["\\", "file"], [DIRECTORY_SEPARATOR, $class], $templatePath);
    if (file_exists($path)) {
        require_once "$path";
        break;
    }
} spl_autoload_register("namespaceAutoload"); 

Im angegebenen Beispiel sucht PHP in diesen drei Verzeichnissen nach dem Namespace \ class unter Verwendung dieser drei verschiedenen Dateinamenformate.

Augusto Santana
quelle