简体   繁体   English

PHP spl_autoload_register

[英]PHP spl_autoload_register

I am trying to take advantage of autoloading in PHP. 我试图利用PHP中的自动加载功能。 I have various classes in different directories, and so I have bootstrapped the autoloading as follows: 我在不同目录中有各种类,因此我按如下方式引导了自动加载:

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

It all seems to work fine, but I just wanted to double check that this is indeed considered acceptable practise. 看起来一切正常,但我只是想仔细检查一下这确实被认为是可以接受的做法。

Sure, looks good. 当然,看起来不错。 The only thing you might do is register them in the order they're most likely to hit. 您唯一可以做的就是按照它们最有可能击中的顺序注册它们。 For example, if your most commonly used classes are in services, then vos, then printers, the order you have is perfect. 例如,如果您最常用的类在服务中,然后是vos,然后是打印机,那么您所拥有的顺序是完美的。 This is because they're queued and called in-order, so you'll achieve slightly better performance by doing this. 这是因为它们按顺序排队并被调用,因此您可以通过这样做来获得更好的性能。

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 . 使用不带参数的spl_autoload_register将注册spl_autoload ,它将在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, eg 没关系,但是如果这些只是某个文件夹下的文件夹,例如

/library
    /JonoB
        /services
        /vos
        /printers

you might want to consider adding these to your classnames, eg 您可能要考虑将它们添加到您的类名中,例如

JonoB_Services_Foo, JonoB_Vos_Bar, JonoB_Printers_Baz

and then split the $classname by the underscore and take each part as folder name. 然后用下划线将$classname分开,并将每个部分作为文件夹名称。 This is similar to PEAR class name convention . 这类似于PEAR类名约定 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. 除了使用PEAR约定样式类名之外,您还可以使用名称空间autoload example ),但是请注意,这些名称空间需要PHP5.3,但在共享托管上尚未广泛使用。 And your application won't be backwards compatible with PHP<5.3 then (if that's an issue). 这样,您的应用程序将不会与PHP <5.3向后兼容(如果这是一个问题)。

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. 因此,如果您按照Gordon的建议为每个类添加前缀,则对于Services_Foo ,自动autoload_services()autoload_services()应该查看“ Services_”是否为$class_name的第一个子字符串,如果没有立即返回false,则可以进行进一步处理,特别是文件系统检查。

If i was supposed to refactor your code , it would be 如果我应该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');    

I have written my own ClassLoader using spl_autoload_register. 我已经使用spl_autoload_register编写了自己的ClassLoader。
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. 我只是将这个文件包含在每个PHP文件中,而不必担心任何include / require指令。
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;
}
?>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM