PHP中的自动加载器 - 一次运行两个

时间:2013-03-20 20:38:11

标签: php wordpress autoload spl autoloader

我理解如何注册自动加载器甚至如何创建自动加载器,这根本不是问题。然而,主要问题是 - 如何让两个自动装载机并排运行:

class project_one_folder_class extends project_two_folder_class{}

您会注意到子类属于一个伸出并调用位于不同项目中的父类的项目。

项目链接的方式项目的两个类总是被自动加载器看到,如何从未见过项目的类。

所以我想到的方法是编写两个自动加载器并注册它们,因为php会查看另一个。 php似乎只在一个而不是另一个中查找。

你怎么解决这个问题?

修改

项目二是父项目,项目一项是项目。这是一个更加扩展的问题,然后是What was posted on this question

为了更好地扩展这是我的班级。

class AisisCore_Loader_AutoLoader{

    protected static $_instance;

    public function get_instance(){
        if(null == self::$_instance){
            self::$_instance = new self();
        }

        return self::$_instance;
    }

    public function reset_instance(){
        self::$_instance = null;
    }

    public function register_auto_loader(){
        spl_autoload_register(array($this, 'load_class'));
        spl_autoload_register(array($this, 'load_child_class'));
    }

    public function load_class($class){
        $path = str_replace('_', '/', $class);
        if(file_exists(get_template_directory() . '/' . $path . '.php')){
            require_once(get_template_directory() . '/' . $path . '.php');
        }
    }

    public function load_child_class($class){
        $path = str_replace('_', '/', $class);
        if(file_exists(get_stylesheet_directory() . '/' . $path . '.php')){
            require_once(get_stylesheet_directory() . '/' . $path . '.php');
        }
    }   
}

目前这个类将在父项目中加载任何内容。它甚至会在子项目中加载父项目对象。但是,如果找不到子类,则无法使用此类加载子对象。

那些熟悉WordPress的人会立即说,是的,因为你需要get_template_directoryget_stylesheet_directory然而 - 知道这一点 - 我想编写两个自动加载器,一个将加载子项目使用get_stylesheet_directory的对象然后通过get_stylesheet_directory加载父对象的对象,以便:

class project_one_folder_class extends project_two_folder_class{}

工作和加载,没有错误。

4 个答案:

答案 0 :(得分:1)

当然,当第一个file_exists返回false时,您可以在同一个自动加载器中查找第二个路径。

您还可以为第二条路径注册第二个自动加载器。

PHP docs解决了这个问题:

  

如果必须有多个自动加载功能,spl_autoload_register()允许这样做。它有效地创建了一个自动加载功能队列,并按照它们的定义顺序遍历每个功能。相比之下,__autoload()可能只定义一次。

答案 1 :(得分:1)

这有点粗糙,但实际上只需要一个只在多个目录中检查的自动加载器:

abstract class Hakre_Theme_AutoLoader
{
    public static $directories;

    public static function init()
    {
        // configure paths
        self::$directories = array(
            get_template_directory(), // current theme, parent in case of childtheme
            get_stylesheet_directory(), // current theme, child in case of childtheme
        );

        // please double check if you really need to prepend
        return spl_autoload_register('Hakre_Theme_AutoLoader::autoload', true, true);
    }

    public static function autoload($class)
    {
        $filename = str_replace('_', '/', $class) . '.php';

        foreach (self::$directories as $directory) {
            $path = $directory . '/' . $filename;
            if (is_file($path)) {
                require($path);
                return; # leave because the class has been loaded
            }
        }
    }
}


Hakre_Theme_AutoLoader::init();

## If you're unsure all worked out properly:
var_dump(Hakre_Theme_AutoLoader::$directories);

这实际上应该这样做,但我还没有测试过。请参阅var_dump,您可以调试是否注册了正确的目录。不需要多次回调只是因为你想签入两个目录。

答案 2 :(得分:1)

分开自动加载过程!

PHP的工作原理如下:在某些时候,代码执行会偶然发现尚未加载的类引用。 $obj = new project_one_folder_class()

现在调用已注册的自动加载器函数,从首先添加的函数开始(除非稍后添加的函数使用“prepend”参数)。

第一个(以及所有后续的)自动加载函数获取应加载的类的名称。该功能现在有权决定

  1. 加载这个课是否是它的任务?如果没有,不做任何事,让其他功能尝试加载它。
  2. 如果此函数负责加载类,请尝试从已知类名中组成路径和文件名,并要求此文件。
  3. 步骤1通常通过查看要加载的类名是否以某个前缀开头来解决。在您的情况下,负责加载以“project_one_”开头的类的自动加载器不应该尝试从其他类开始加载任何其他类。

    如果自动装带器知道它必须执行自动加载,则执行步骤2。它现在将类名转换为相对路径和文件名,添加基目录,然后需要该文件。

    要求定义扩展另一个类(或实现接口)的类的文件然后可以触发另一个自动加载的任何未知类的运行。在您的情况下,再次启动自动加载过程,类名为“project_two_folder_class”。请注意,将使用此第二个类名称再次调用“project_one_”类的第一个自动加载器,但它不能执行任何操作,因为它不知道如何加载这些类。这取决于知道“project_two_”类的自动加载器。

    注册顺序对于不同的自动加载器无关紧要。如果是这样,自动装载机行为不端。

    因为简单地将类名中的任何下划线字符转换为DIRECTORY_SEPARATOR以及命名空间中的反斜杠是一种常见模式,所以最后添加“.php”,然后尝试从定义的基本目录中加载此文件,这两个自动加载器的代码是相同的,并且问题被简化为只配置一个自动加载功能,这两种情况:应该存在哪个前缀,以及文件应该在哪个基本目录中,前提是类名可以转换为文件的相对路径。

    每次检查文件是否存在于某个目录中都不是最佳性能。您最终会对文件进行大量检查,只需查看类名,您就无法加载这些文件。

    顺便说一句:自动加载器功能不需要是单例。实际上,你的单例实现是破坏的,没用。使用new实例化自动加载器,可能会将一些配置值传递给构造函数,并调用spl_autoload_register(),您应该完成。

答案 3 :(得分:0)

您可以添加多个加载器,只需使用spl_autoload_register()注册每个函数。

程序风格:

spl_autoload_register('loader_function1'));
 // your second class location
spl_autoload_register('loader_function2'));

或以OO风格

spl_autoload_register(array($this, 'loader_function1'));
spl_autoload_register(array($this, 'loader_function2'));

然而,基于您的问题:您可以通过使用更灵活的自动加载器来完成相同的任务 在这里看到我的答案在另一个问题: Class autoloader in wordpress plugin

相关问题