Co to jest automatyczne ładowanie; Jak korzystać ze spl_autoload, __autoload i spl_autoload_register?


203

Uczę się zaawansowanych standardów PHP i staram się wdrażać nowe i przydatne metody. Wcześniej używałem __autoloadtylko do ucieczki, włączając wiele plików na każdej stronie, ale ostatnio widziałem wskazówkę dotyczącą__autoload manual

spl_autoload_register () zapewnia bardziej elastyczną alternatywę dla klas autoloadingu. Z tego powodu używanie __autoload () jest odradzane i może być przestarzałe lub usunięte w przyszłości.

ale tak naprawdę nie mogę wymyślić, jak wdrożyć spl_autoloadispl_autoload_register

Odpowiedzi:


334

spl_autoload_register() pozwala zarejestrować wiele funkcji (lub metod statycznych z własnej klasy Autoload), które PHP umieści w stosie / kolejce i wywoła sekwencyjnie, gdy zadeklarowana zostanie „nowa klasa”.

Na przykład:

spl_autoload_register('myAutoloader');

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

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

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

$myClass = new MyClass();

W powyższym przykładzie „MyClass” to nazwa klasy, którą próbujesz utworzyć, PHP przekazuje tę nazwę jako ciąg znaków spl_autoload_register(), co pozwala ci pobrać zmienną i użyć jej do „włączenia” odpowiedniej klasy / pliku . W rezultacie nie musisz specjalnie uwzględniać tej klasy za pomocą instrukcji włączania / żądania ...

Wystarczy wywołać klasę, którą chcesz utworzyć, jak w powyższym przykładzie, a ponieważ zarejestrowałeś własną funkcję (via spl_autoload_register()), która zorientuje się, gdzie znajdują się wszystkie klasy, PHP użyje tej funkcji.

Zaletą korzystania spl_autoload_register()jest to, że w przeciwieństwie do __autoload()tego, nie trzeba implementować funkcji automatycznego ładowania w każdym tworzonym pliku. spl_autoload_register()pozwala także zarejestrować wiele funkcji automatycznego ładowania, aby przyspieszyć automatyczne ładowanie i jeszcze bardziej ułatwić.

Przykład:

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
    }

W odniesieniu do spl_autoload instrukcja mówi:

Ta funkcja ma być używana jako domyślna implementacja dla __autoload(). Jeśli nic innego nie zostanie określone i nie spl_autoload_register()zostanie wywołane bez żadnych parametrów, funkcje te zostaną wykorzystane do późniejszego wywołania __autoload().

Mówiąc prościej, jeśli wszystkie pliki znajdują się w jednym katalogu, a aplikacja używa nie tylko plików .php, ale także niestandardowych plików konfiguracyjnych z rozszerzeniami .inc, na przykład, jedną ze strategii, którą można zastosować, byłoby dodanie katalogu zawierającego wszystkie pliki do PHP zawierają ścieżkę (via set_include_path()).
A ponieważ potrzebujesz również plików konfiguracyjnych, użyjesz spl_autoload_extensions()listy rozszerzeń, których ma szukać PHP.

Przykład:

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

Ponieważ spl_autoload jest domyślną implementacją __autoload()magicznej metody, PHP wywoła spl_autoload podczas próby utworzenia nowej klasy.

Mam nadzieję że to pomoże...


35
To może być jedna z najlepszych odpowiedzi w historii odpowiedzi. Szacunek. Miałem jedno z tych „OMG! Teraz wszystko ma sens!” chwile z twojego powodu, mój dobry człowieku. Myślę, że mógłbym po prostu założyć fanklub.
Just Plain High

2
Aby była to najlepsza odpowiedź spośród wszystkich odpowiedzi, nawet w alternatywnych wszechświatach, dodaj, że spl_autoload bardzo, um, „pomocnie” (?) Konwertuje wszystkie nazwy plików na małe litery (patrz mój komentarz do @user poniżej). Nie możesz użyć waniliowej spl_autoload_register (), jeśli podoba Ci się Twój CapitalLettersAndStuff.
Just Plain High

6
@ Just Plain High Nie mam tego problemu, a wszystkie moje pliki klas są przechowywane w kasecie. BTW, to wspaniała odpowiedź. Pomogło mi to zrozumieć prostą koncepcję, której nie mogłem zrozumieć, dopóki nie przeczytam tego postu! Moja linia 85 (i rosnąca) zawiera plik, który obejmuje wszystkie pliki mojej klasy, ma teraz 7 linii!
kyle

2
To rzeczywiście dobra odpowiedź, ale brakuje mi jednej rzeczy. Jaka jest rzeczywista domyślna funkcjonalność? W klasach, które znam, używa przestrzeni nazw jako ścieżki, a nazwa klasy jako nazwy pliku. Chociaż nie mogę zrozumieć, jak to działa z funkcjami.
SiXoS,

2
Czy nie jest jedną z ogromnych korzyści z używania spl_autoload_register()(i __autoload()ogólnie) tego, że leniwe ładunki obejmują pliki / klasy? Jest to sugerowane przez odpowiedź, ale nie jest wyraźnie określone. Dla mnie jest to krytyczna informacja, która byłaby idealna do włączenia do twojej odpowiedzi! :)
rinogo

13

Od PHP 5.3 możesz używać spl_autoload_register()przestrzeni nazw, co oznacza, że ​​możesz organizować swój projekt i automatycznie ładować swoje klasy php bez żadnych wymagań, bez włączania i bez redefiniowania __autoload()funkcji.

Aby zademonstrować to zachowanie, po prostu utwórz plik o nazwie index.php:

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

Następnie utwórz folder o nazwie Main znajdujący się obok pliku index.php. Na koniec tworzy plik o nazwie Application.php umieszczony w Main i wklej do niego następujący kod:

<?php namespace Main;
class Application{}

9
Notatka z mojego majstrowania przy tym wszystkim: spl_autoload () - a zatem spl_autoload_register () - konwertuje nazwy plików na małe litery (pomimo zgłoszeń błędów, próśb i wściekłego głosowania). Oznacza to , że możesz szukać „Main \ Application”, ale spl_autoload szuka „main \ application”. Jeśli lubisz wielbłądy, tak jak ja, będziesz musiał napisać własną funkcję. Jest tu dobry przykład na początek: github.com/ircmaxell/PHP-CryptLib/blob/…
Just Plain High

1
Plusy: spl_autoload_register () jest najszybszą metodą automatycznego ładowania Wady: będzie działał tylko z małymi plikami / klasami, a także z przestrzeniami nazw, które w tym dniu i wieku po prostu sux są duże (nie ma opcji, aby kazać mu używać CamelCase itp.). Ale jeśli możesz żyć ze strukturą namespace / classname.php, nie szukaj dalej.
stamster,

1
spl_autoload_register()domyślna implementacja nie może znaleźć odziedziczonych klas. Tak więc używając domyślnych, małych liter i katalogów odzwierciedlających ścieżkę przestrzeni nazw, wszystko działa dobrze, chyba że mam klasę, która rozszerza inną klasę (rodzica). Następnie PHP zgłasza błąd, że nie może znaleźć tej klasy nadrzędnej, nawet jeśli wszystkie są w tym samym katalogu / przestrzeni nazw! Mylące jest to, że dosłownie można znaleźć tylko klasy pierwszego poziomu, więc musiałem umieścić kolejną spl_autoload_register()z anonimową regułą funkcji tuż po pierwszej, aby ręcznie włączyć brakujące klasy nadrzędne / dziedziczone.
stamster

1

Oto sposób korzystania z funkcji Autoload. W podanym przykładzie chcę załadować klasy z 3 różnych katalogów.

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"); 

W podanym przykładzie PHP wyszuka przestrzeń nazw \ class w tych trzech katalogach, używając tych trzech różnych formatów nazw plików.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.