什么是自动加载;如何使用spl_autoload,__ autoload和spl_autoload_register?


203

我正在学习高级PHP标准,并尝试实现新的有用方法。之前,我__autoload只是为了转义而在每个页面上包含多个文件,但是最近我看到了一个提示__autoload manual

spl_autoload_register()为自动加载类提供了更灵活的替代方法。因此,不建议使用__autoload(),以后可能不建议使用或将其删除。

但我真的不知道如何实施spl_autoloadspl_autoload_register

Answers:


334

spl_autoload_register() 允许您注册PHP将放入堆栈/队列中的多个函数(或您自己的Autoload类中的静态方法),并在声明“新类”时顺序调用。

因此,例如:

spl_autoload_register('myAutoloader');

function myAutoloader($className)
{
    $path = '/path/to/class/';

    include $path.$className.'.php';
}

//-------------------------------------

$myClass = new MyClass();

在上面的示例中,“ MyClass”是您要实例化的类的名称,PHP将该名称作为字符串传递给spl_autoload_register(),从而允许您选择变量并将其用于“包含”适当的类/文件。因此,您不需要特别通过include / require语句来包含该类。

就像上面的示例一样,只需简单地调用您想要实例化的类,并且由于您注册了spl_autoload_register()自己的函数(通过)即可确定所有类的位置,因此PHP将使用该函数。

使用的好处spl_autoload_register()是,与__autoload()您不同的是,您不需要在创建的每个文件中实现自动加载功能。spl_autoload_register()还可以让您注册多个自动加载功能,以加快自动加载并使其更加容易。

例:

spl_autoload_register('MyAutoloader::ClassLoader');
spl_autoload_register('MyAutoloader::LibraryLoader');
spl_autoload_register('MyAutoloader::HelperLoader');
spl_autoload_register('MyAutoloader::DatabaseLoader');

class MyAutoloader
{
    public static function ClassLoader($className)
    {
         //your loading logic here
    }


    public static function LibraryLoader($className)
    {
         //your loading logic here
    }

关于spl_autoload,手册指出:

该功能旨在用作的默认实现__autoload()。如果未指定其他内容且spl_autoload_register()没有任何参数调用该函数,则此函数将用于以后对的任何调用__autoload()

实际上,如果所有文件都位于一个目录中,并且您的应用程序不仅使用.php文件,而且还使用扩展名为.inc的自定义配置文件,那么您可以使用的一种策略是添加包含所有内容的目录文件到PHP的包含路径(通过set_include_path())。
而且,由于还需要配置文件,因此将用于spl_autoload_extensions()列出要PHP查找的扩展名。

例:

set_include_path(get_include_path().PATH_SEPARATOR.'path/to/my/directory/');
spl_autoload_extensions('.php, .inc');
spl_autoload_register();

由于spl_autoload是__autoload()magic方法的默认实现,因此当您尝试实例化新类时,PHP将调用spl_autoload。

希望这可以帮助...


35
这可能是有史以来最好的答案之一。尊重。我有一个“ OMG!现在一切都有意义了!” 瞬间因为你,我的好人。我想我可能只是开一个粉丝俱乐部。
Just Plain High

2
为了使它成为所有替代答案中最好的答案,请补充一点,spl_autoload嗯,“有帮助”(?)会将所有文件名都转换为小写(请参阅下面对@user的评论)。如果您喜欢CapitalLettersAndStuff,则不能使用spl_autoload_register()香草。
只是普通高

6
@Just Plain High我没有这个问题,我所有的课程文件都被驼峰包装。顺便说一句,这是一个很好的答案。它帮助我了解了一个简单的概念,直到我读了这篇文章我才明白!我的85(并且还在不断增长)的包含文件的行现在包括7行!
凯尔2014年

2
这确实是一个很好的答案,但我缺少一件事。实际的默认功能是什么?对于我知道的类,它使用名称空间作为路径,使用类名称作为文件名。尽管我不知道它如何与函数一起工作。
SiXoS 2014年

2
使用(通常)延迟加载包括文件/类的巨大好处不是其中之一吗?答案暗示了这一点,但没有明确说明。对我来说,这是至关重要的信息,非常适合包含在您的答案中!:)spl_autoload_register()__autoload()
rinogo 2015年

13

从PHP 5.3开始,您可以使用spl_autoload_register()名称空间,这意味着您可以组织项目并自动加载php类,而无需任何要求或包含,也无需重新定义__autoload()函数。

为了演示这种行为,只需创建一个名为index.php的文件:

<?php
spl_autoload_register();
var_dump(new Main\Application);

然后在index.php文件旁边创建一个名为Main的文件夹。最后,在Main中创建一个名为Application.php的文件,并将以下代码粘贴到其中:

<?php namespace Main;
class Application{}

9
我对所有这些事情有所了解的注释:spl_autoload()-从而spl_autoload_register()-将文件名转换为小写(尽管有错误报告,恳求和愤怒的投票)。这意味着可能正在寻找“ Main \ Application”,但spl_autoload正在寻找“ main \ Application”。如果像我一样喜欢骆驼,您将不得不编写自己的函数。有一个很好的例子首发的位置:github.com/ircmaxell/PHP-CryptLib/blob/...
只是普通的高

1
优点:spl_autoload_register()是自动加载的最快方法缺点:它仅适用于小写文件/类和名称空间,在当今,这种情况仅会占用大量时间(无法选择告诉它使用CamelCase等)。但是,如果您可以使用namespace / classname.php结构,请不要再看了。
stamster

1
spl_autoload_register()默认实现无法找到继承的类。因此,使用默认值,小写的文件和反映名称空间路径的目录,除非我拥有扩展另一个类(父类)的类,否则一切都可以正常工作。然后,PHP引发错误,即使它们都在同一目录/名称空间中,也找不到该父类!令人困惑的是,实际上只能找到一级类,因此我不得不spl_autoload_register()在第一个类之后放置另一个具有匿名函数规则的类,以便手动包括丢失的父类/继承的类。
stamster

1

这是我使用自动加载的方式。在给定的示例中,我希望从3个不同的目录中加载类。

function namespaceAutoload($rawClass){

$class = str_replace('\\', DIRECTORY_SEPARATOR, $rawClass);

$possiblePaths[] = '..\sys\class\file.php';
$possiblePaths[] = '..\sys\class\lib\file.php';
$possiblePaths[] = '..\sys\class\class.file.inc.php';

foreach ($possiblePaths as $templatePath) {
    $path = str_replace(["\\", "file"], [DIRECTORY_SEPARATOR, $class], $templatePath);
    if (file_exists($path)) {
        require_once "$path";
        break;
    }
} spl_autoload_register("namespaceAutoload"); 

在给定的示例中,PHP将使用这三种不同的文件名格式在这三个目录中查找namespace \ class。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.