Domanda

Come la maggior parte sviluppatori web in questi giorni, io sto bene a godere dei vantaggi di solida architettura MVC per applicazioni web e siti. Quando si fa MVC con PHP, caricamento automatico viene ovviamente in estremamente pratico.

Sono diventato un fan di spl_autoload_register sopra definisce semplicemente una singola funzione __autoload(), in quanto questo è, ovviamente, più flessibile se si sta integrando diversi moduli base che ogni utilizzano il proprio caricamento automatico. Tuttavia, non ho mai sentito grande circa le funzioni di carico che scrivo. Essi comportano un sacco di controllo stringa e scansione di directory, al fine di cercare possibili classi da caricare.

Per esempio, diciamo che ho un app che ha un percorso di base definita come PATH_APP, e una struttura semplice con le directory di nome models, views e controllers. Mi capita spesso di impiegare una struttura di nomi per cui file sono denominati IndexView.php e IndexController.php all'interno della directory appropriata, e modelli in genere non hanno alcun programma particolare per impostazione predefinita. Potrei avere una funzione loader per questa struttura come questa che viene iscritto su spl_autoload_register:

public function MVCLoader($class)
{
    if (file_exists(PATH_APP.'/models/'.$class.'.php')) {
        require_once(PATH_APP.'/models/'.$class.'.php');
        return true;
    }
    else if (strpos($class,'View') !== false) {
        if (file_exists(PATH_APP.'/views/'.$class.'.php')) {
            require_once(PATH_APP.'/views/'.$class.'.php');
            return true;
        }
    }
    else if (strpos($class,'Controller') !== false) {
        if (file_exists(PATH_APP.'/controllers/'.$class.'.php')) {
            require_once(PATH_APP.'/controllers/'.$class.'.php');
            return true;
        }
    }
    return false;
}

Se non viene trovato dopo che, potrei avere un'altra funzione per la scansione di sub-directory nella directory modelli. Tuttavia, tutte le if / else-ing, stringa di controllo e la scansione di directory sembra inefficiente per me, e mi piacerebbe migliorarlo.

Sono molto curioso di ciò che la denominazione dei file e le strategie di caricamento automatico di altri sviluppatori potrebbero impiegare. Sto cercando specificamente per buone tecniche da impiegare per il caricamento automatico efficiente, e non alternative a caricamento automatico.

È stato utile?

Soluzione

Questo è quello che ho utilizzato in tutti i miei progetti (sollevato direttamente dalla fonte del l'ultimo):

public static function loadClass($class)
{
    $files = array(
        $class . '.php',
        str_replace('_', '/', $class) . '.php',
    );
    foreach (explode(PATH_SEPARATOR, ini_get('include_path')) as $base_path)
    {
        foreach ($files as $file)
        {
            $path = "$base_path/$file";
            if (file_exists($path) && is_readable($path))
            {
                include_once $path;
                return;
            }
        }
    }
}

Se cerco SomeClass_SeperatedWith_Underscores cercherà SomeClass_SeperatedWith_Underscores.php seguito da SomeClass / SeperatedWith / Underscores.php radice in ogni directory nella corrente percorso di inclusione.

Modifica Volevo solo mettere là fuori che io uso questo per l'efficienza in fase di sviluppo, e non necessariamente il tempo di elaborazione. Se si dispone di PEAR sul vostro cammino, allora con questo si può semplicemente utilizzare le classi e non hanno di includerli quando ne hai bisogno.

Io tendo a tenere le mie classi in una gerarchia di directory, con sottolineature rottura fino namespace ... Questo codice mi permette di mantenere la struttura di file bella e ordinata se voglio, o per iniettare un file di classe rapido senza directory nidificate se io desiderare (per l'aggiunta di una singola classe o due per una libreria che è convenuto, ma non fa parte del progetto attualmente sto lavorando su.)

Altri suggerimenti

Sono atterrato su questa soluzione:

ho creato un singolo script che attraversa la mia cartella di libreria di classi (che contiene sottocartelle per moduli separati / sistemi), e analizza il contenuto del file alla ricerca di definizioni di classi. Se trova una definizione di classe in un file php (abbastanza semplice schema di espressione regolare), si crea un link simbolico:

class_name.php -> actual/source/file.php

Questo mi permette di utilizzare un unico, semplice funzione autoload che ha bisogno solo il nome della classe e il percorso della cartella principale collegamento simbolico, e non hanno a che fare qualsiasi manipolazione percorso / string.

La parte migliore è che posso riorganizzare il mio codice sorgente, in tutto o aggiungere un nuovo sottosistema e basta eseguire lo script di collegamento generatrice di avere tutto caricato automaticamente.

Se si desidera che l'efficienza allora non dovrebbe usare la funzione di caricamento automatico a tutti. La funzione di caricamento automatico è per essere pigro. Si dovrebbe essere fornendo un percorso esplicito per i tuoi file include quando li si include. Se la funzione di caricamento automatico in grado di trovare questi file allora si potrebbe codice per trovare loro in modo esplicito. Quando si lavora sulla parte vista del codice e in procinto di caricare una nuova classe di visualizzazione, lasciando la funzione di caricamento automatico gestirlo, ma prima assume la classe è una classe del modello? Questo è inefficiente. Invece il codice dovrebbe essere solo:

include_once $this->views_path . $class . '.php';

Se avete bisogno di più percorsi "vista", fare una funzione che carica vista:

public function load_view($class) {
    // perhaps there's a mapping here instead....
    foreach ($this->views_paths as $path) {
        $filename = $path . $class . '.php';
        if (file_exists($filename)) {
            include_once $filename;
        }
    }
    throw ....
}

In ogni caso, nel punto in cui si verifica l'inclusione, si ha il più grande / informazioni più accurate sulla classe che si desidera caricare. Utilizzando queste informazioni per caricare completamente la classe è l'unica strategia di caricamento delle classi efficiente. Sì, si può finire con più variabili di classe o (il cielo non voglia) alcune variabili globali. Ma questo è un compromesso più che essere solo parti pigri e di scansione del file system per la classe.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top