Che cos'è il caricamento automatico; Come si usa spl_autoload, __autoload e spl_autoload_register?


204

Sto imparando standard PHP avanzati e sto cercando di implementare metodi nuovi e utili. Prima usavo __autoloadsolo per sfuggire includendo più file su ogni pagina, ma recentemente ho visto un suggerimento su__autoload manual

spl_autoload_register () fornisce un'alternativa più flessibile per le classi di caricamento automatico. Per questo motivo, l'utilizzo di __autoload () è sconsigliato e potrebbe essere deprecato o rimosso in futuro.

ma non riesco davvero a capire come implementare spl_autoloadespl_autoload_register

Risposte:


335

spl_autoload_register() consente di registrare più funzioni (o metodi statici della propria classe di caricamento automatico) che PHP inserirà in uno stack / coda e chiamerà in sequenza quando viene dichiarata una "nuova classe".

Quindi per esempio:

spl_autoload_register('myAutoloader');

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

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

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

$myClass = new MyClass();

Nell'esempio sopra, "MyClass" è il nome della classe che si sta tentando di creare un'istanza, PHP passa questo nome come stringa a spl_autoload_register(), che consente di raccogliere la variabile e utilizzarla per "includere" la classe / il file appropriati . Di conseguenza non è necessario includere specificamente quella classe tramite un'istruzione include / request ...

Basta semplicemente chiamare la classe che si desidera creare un'istanza come nell'esempio sopra, e poiché hai registrato una tua funzione (via spl_autoload_register()) che capirà dove si trova tutta la tua classe, PHP utilizzerà quella funzione.

Il vantaggio dell'utilizzo spl_autoload_register()è che a differenza di __autoload()te non è necessario implementare una funzione di caricamento automatico in ogni file che crei. spl_autoload_register()consente inoltre di registrare più funzioni di caricamento automatico per accelerare il caricamento automatico e renderlo ancora più semplice.

Esempio:

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
    }

Per quanto riguarda spl_autoload , il manuale afferma:

Questa funzione deve essere utilizzata come implementazione predefinita per __autoload(). Se non viene specificato nient'altro e spl_autoload_register()viene chiamato senza parametri, questa funzione verrà utilizzata per qualsiasi chiamata successiva a __autoload().

In termini più pratici, se tutti i file si trovano in una singola directory e l'applicazione utilizza non solo file .php, ma file di configurazione personalizzati con estensioni .inc, ad esempio, una strategia che potresti utilizzare sarebbe quella di aggiungere la tua directory contenente tutti i file nel percorso di inclusione di PHP (via set_include_path()).
E poiché hai bisogno anche dei tuoi file di configurazione, dovresti spl_autoload_extensions()elencare le estensioni che vuoi che PHP cerchi.

Esempio:

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

Poiché spl_autoload è l'implementazione predefinita del __autoload()metodo magico, PHP chiamerà spl_autoload quando proverai ad istanziare una nuova classe.

Spero che questo ti aiuti...


35
Questa potrebbe essere una delle migliori risposte nella storia delle risposte di sempre. Rispetto. Ho avuto uno di quelli "OMG! Adesso ha tutto il senso!" momenti grazie a te, mio ​​buon uomo. Penso che potrei semplicemente aprire un fan club.
Semplicemente alto il

2
Per rendere questa la migliore risposta di tutte le risposte mai anche in universi alternativi, aggiungi che spl_autoload molto, ehm, "utile" (?) Converte tutti i nomi di file in minuscolo (vedi il mio commento a @user di seguito). Non puoi usare la vaniglia spl_autoload_register () se ti piacciono i tuoi CapitalLettersAndStuff.
Semplicemente alto il

6
@Just Plain High Non ho riscontrato questo problema e tutti i miei file di classe sono camelcasati. A proposito, questa è una risposta meravigliosa. Mi ha aiutato a capire meglio un concetto che non riuscivo a capire fino a quando non ho letto questo post! La mia 85 (e crescente) riga include il file che include tutti i miei file di classe ora è 7 righe!
Kyle,

2
Questa è davvero una buona risposta ma mi manca una cosa. Qual è la funzionalità predefinita effettiva? Con le classi che conosco, utilizza lo spazio dei nomi come percorso e il nome della classe come nome file. Anche se non riesco a capire come funziona con le funzioni.
SiXoS,

2
Uno dei grandi vantaggi dell'uso spl_autoload_register()(e __autoload()in generale) del fatto che i carichi pigri non sono i file / le classi? Ciò è implicito nella risposta, ma non dichiarato esplicitamente. Per me, queste sono informazioni critiche che sarebbero perfette per l'inclusione nella tua risposta! :)
Rinogo,

13

A partire da PHP 5.3, puoi utilizzare gli spl_autoload_register()spazi dei nomi, il che significa che puoi organizzare il tuo progetto e caricare automaticamente le tue classi php senza alcun bisogno o inclusione e senza ridefinire una __autoload()funzione.

Per dimostrare questo comportamento, basta creare un file chiamato index.php:

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

Quindi crea una cartella denominata Main situata proprio accanto al file index.php. Infine, crea un file chiamato Application.php situato in Main e incolla il seguente codice:

<?php namespace Main;
class Application{}

9
Una nota del mio armeggiare con tutto questo: spl_autoload () - e quindi spl_autoload_register () - converte i nomi dei file in minuscolo (nonostante segnalazioni di bug, motivi e votazione furiosa). Questo significa che potresti cercare "Main \ Application" ma spl_autoload sta cercando "main \ application". Se ti piacciono i cammelli, come me, dovrai scrivere la tua funzione. C'è un bell'esempio di partenza qui: github.com/ircmaxell/PHP-CryptLib/blob/…
Just Plain High

1
Pro: spl_autoload_register () è il metodo più veloce per caricare automaticamente i contro: funzionerà solo con file / classi minuscoli e anche spazi dei nomi, che al giorno d'oggi e solo sux alla grande (nessuna opzione per dirgli di usare CamelCase ecc.). Ma se puoi vivere con la struttura namespace / classname.php, non cercare oltre.
Criceto

1
spl_autoload_register()l'implementazione predefinita non è in grado di trovare le classi ereditate. Quindi, usando valori predefiniti, file minuscoli e directory che riflettono il percorso dello spazio dei nomi, tutto funziona bene a meno che non abbia una classe che estende un'altra classe (padre). PHP quindi genera l'errore che non riesce a trovare quella classe genitore, anche se sono tutti nella stessa directory / spazio dei nomi! Ciò che confonde è che sono state trovate letteralmente solo classi di primo livello, quindi ho dovuto spl_autoload_register()inserirne un'altra con una regola di funzione anonima subito dopo la prima per includere manualmente le classi genitore / ereditate mancanti.
Criceto

1

Ecco come utilizzo Autoload. Nell'esempio dato, voglio caricare le classi da 3 diverse directory.

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

Nell'esempio dato, il PHP cercherà lo spazio dei nomi \ class in queste tre directory usando questi tre diversi formati di file.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.