Domanda

Sto cercando di approfittare di caricamento a PHP. Ho varie classi in diverse directory, e così ho bootstrap il caricamento automatico come segue:

function autoload_services($class_name)
{
    $file = 'services/' . $class_name. '.php';
    if (file_exists($file))
    {
        require_once($file);
    }
}

function autoload_vos($class_name)
{
    $file = 'vos/' . $class_name. '.php';
    if (file_exists($file))
    {
        require_once($file);
    }
}

function autoload_printers($class_name)
{
    $file = 'printers' . $class_name. '.php';
    if (file_exists($file))
    {
        require_once($file);
    }
}

spl_autoload_register('autoload_services');
spl_autoload_register('autoload_vos');
spl_autoload_register('autoload_printers');

Tutto sembra funzionare bene, ma volevo solo controllare due volte che questa è davvero considerata pratica accettabile.

È stato utile?

Soluzione

Certo, sembra buono. L'unica cosa che si potrebbe fare è registrarle nell'ordine in cui sono più probabilità di colpire. Ad esempio, se le classi più comunemente usati sono nel settore dei servizi, poi vos, quindi Stampanti, l'ordine che hai è perfetto. Questo è perché sono in coda e chiamati in ordine, così potrai ottenere prestazioni leggermente migliori in questo modo.

Altri suggerimenti

You could use:

set_include_path(implode(PATH_SEPARATOR, array(get_include_path(), './services', './vos', './printers')));
spl_autoload_register();

Using spl_autoload_register without arguments will register spl_autoload which will look for the class name in the directories of the include path. Note that this will lowercase the class name before looking for it on the filesystem.

It's okay, but if these are just folders below a certain folder, e.g.

/library
    /JonoB
        /services
        /vos
        /printers

you might want to consider adding these to your classnames, e.g.

JonoB_Services_Foo, JonoB_Vos_Bar, JonoB_Printers_Baz

and then split the $classname by the underscore and take each part as folder name. This is similar to PEAR class name convention. This way you would only have one loader.

Instead of PEAR convention style classnames, you can also use namespaces (autoload example), but be aware that these require PHP5.3 which is not widely available on shared hosting yet. And your application won't be backwards compatible with PHP<5.3 then (if that's an issue).

Good advice from all the other answers.

Let me add that each autoloader should first check if it even cares about the class being passed in, and return immediately if not.

So if you do as Gordon suggests and add a prefix to each class, then for Services_Foo the autoloader autoload_services() should see if "Services_" is the first substring of $class_name, and if not return false immediately to save on any further processing, especially filesystem checks.

If i was supposed to refactor your code, it would be

function custom_autoload($class_name){
        $dirs = array('services','vos','printers') 
        foreach($dirs as $dir){ 
            $file = $dir.'/'.$class_name. '.php';
            if (file_exists($file)){
               require $file;
               break; // if i have maintained naming conventions as per dir as there
                  // is no point for looking eg: sample1_printer.php in the vos/ 
                 // or printer/. this way iam avoiding unnecessary loop
             }
        }
 }
    spl_autoload_register('custom_autoload');    

I have written my own ClassLoader using spl_autoload_register.
The advantage is that the function looks in every subfolder starting in the current folder.
I simply include this file in every PHP file and never have to worry about any include/require directive.
It simply works :-)

<?php
spl_autoload_register('AutoLoadClasses');

/************************************************************************************
 * AutoLoadClasses
 *
 * Diese Funktion lädt Klassen in gleichnamigen Dateien bei Bedarf automatisch nach,
 * sobald eine (bis dahin unbekannte) Klasse erstmalig instanziert wird.
 * $var = new MeineKlasse; => Es wird nach der Datei class_MeineKlasse.php gesucht
 * Die Suche erfolgt rekursiv in allen Unterordnern ausgehend von dem Ordner, in dem
 * das aufrufende PHP-Script liegt.
 *
 * Michael Hutter / Dezember 2017
 */
function AutoLoadClasses($Klassenname, $StartOrdner = null)
{
    if (is_null($StartOrdner))
    {
        $StartOrdner = __DIR__; # Ausgangspunkt für die Suche: Ordner, in dem sich das aufrufende PHP-Script befindet
        $StartInstanz = true;
    }
    $ZielDateiname = "class_$Klassenname.php";
    $FileList = scandir($StartOrdner, 1); # Sortierung 1 => kommt schneller zum Ziel, falls Ordnernamen im allgemeinen mit einem Großbuchstaben beginnen
    foreach ($FileList as $file) # Alle Dateien und Ordner durchgehen
    {
        $Vollpfad = $StartOrdner.DIRECTORY_SEPARATOR.$file;
        if (is_dir($Vollpfad) && (substr($file, 0, 1) !== '.')) # Ordner?
        {
            #echo "Ordner $StartOrdner<br>";
            $result = AutoLoadClasses($Klassenname, $Vollpfad);
            if ($result) return; # Abbruch, falls Ziel gefunden
        }
        else if (preg_match('/\.php$/i' , $file)) # .php-Datei?
        {
            #echo "$file<br>";
            if ($file == $ZielDateiname) # Dateiname entspricht Klassenname?
            {
                include $Vollpfad;
                return true; # Abbruch aller Rekursionen, da Ziel gefunden
            }
        }
    }
    if (isset($StartInstanz))
        die("<table border bgcolor=red><tr><td>Fehler: Die Datei <b>$ZielDateiname</b> konnte in keinem der Unterordner gefunden werden!</td></tr></table>");
    return false;
}
?>
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top