Подтвердить что ты не робот

PHP spl_autoload_register

Я пытаюсь использовать автозагрузку в PHP. У меня разные классы в разных каталогах, поэтому я загрузил автозагрузку следующим образом:

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

Все работает нормально, но я просто хотел проверить, что это действительно считается приемлемой практикой.

4b9b3361

Ответ 1

Конечно, выглядит хорошо. Единственное, что вы можете сделать, это зарегистрировать их в том порядке, в котором они, скорее всего, попадут. Например, если ваши наиболее часто используемые классы находятся в сервисах, тогда vos, а затем принтеры, ваш заказ отлично. Это происходит из-за того, что они поставлены в очередь и вызваны в порядке, поэтому вы достигнете немного лучшей производительности, выполнив это.

Ответ 2

Вы можете использовать:

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

Используя spl_autoload_register без аргументов, зарегистрируется spl_autoload, который будет искать имя класса в каталогах include path. Обратите внимание, что это приведет к изменению имени класса перед его поиском в файловой системе.

Ответ 3

Все в порядке, но если это только папки под определенной папкой, например

/library
    /JonoB
        /services
        /vos
        /printers

вы можете захотеть добавить их в свои имена классов, например.

JonoB_Services_Foo, JonoB_Vos_Bar, JonoB_Printers_Baz

а затем разделите $classname на знак подчеркивания и возьмите каждую часть в качестве имени папки. Это похоже на соглашение о названии класса PEAR. Таким образом, у вас будет только один загрузчик.

Вместо названий классов стиля PEAR вы также можете использовать namespaces (пример автозагрузки), но имейте в виду, что для них требуется PHP5.3, который пока не широко доступен на общедоступном хостинге. И ваше приложение не будет обратно совместимо с PHP < 5.3, тогда (если это проблема).

Ответ 4

Хороший совет от всех других ответов.

Позвольте мне добавить, что каждый автозагрузчик должен сначала проверить, не заботится ли он о том, что класс передан, и немедленно вернуться, если нет.

Итак, если вы делаете то, что предлагает Гордон и добавляете префикс для каждого класса, то для Services_Foo автозагрузчик autoload_services() должен видеть, является ли "Services_" первой подстрокой $class_name, а если не возвращать false немедленно, за исключением дальнейшей обработки, особенно проверки файловой системы.

Ответ 5

Если я должен был refactor your code, это было бы

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

Ответ 6

Я написал собственный ClassLoader, используя spl_autoload_register.
Преимущество заключается в том, что функция просматривается в каждой подпапке, начиная с текущей папки.
Я просто включаю этот файл в каждый файл PHP и никогда не должен беспокоиться о какой-либо директиве include/require.
Он просто работает: -)

<?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;
}
?>