Вопрос

Я пытаюсь воспользоваться автозагрузкой в ​​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');

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

Это было полезно?

Решение

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

Другие советы

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

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

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

Ничего страшного, но если это просто папки ниже определенной папки, например.

/library
    /JonoB
        /services
        /vos
        /printers

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

JonoB_Services_Foo, JonoB_Vos_Bar, JonoB_Printers_Baz

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

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

Хороший совет из всех остальных ответов.

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

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

Если бы я должен был 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');    

Я написал свой собственный 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;
}
?>
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top