2

I understand how to register autoloaders and even how to create one, that's no issue at all. How ever the main issue is - how do you have two auto loaders running side by side for something like:

class project_one_folder_class extends project_two_folder_class{}

You'll notice that the child class belongs to a project which is reaching out and calling the parent class which is locate in a different project.

The way the projects are linked project two's classes are always seen by the auto loader, how ever project one's classes are never seen.

So the way I thought around this was to write two auto loaders and register them because php will look in on then the other. How ever php seems to be looking in only one and not the other.

how would you solve this?

Edit

Project two is parent, Project one is child. This is more expanded question then What was posted on this question.

To better expand this is my class.

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

Currently this class will load anything in the parent project. It will even load parent project objects in the child project. How ever no child object can be loaded using this class as it is not found.

Those familiar with WordPress will instantly say, yes its because you have get_template_directory when you want get_stylesheet_directory How ever - Knowing this - I want to write then two auto loaders, one that will load child projects objects using get_stylesheet_directory and then one that will load parent objects via get_stylesheet_directory so that:

class project_one_folder_class extends project_two_folder_class{}

works and loads, with out error.

4

4 回答 4

1

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

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

PHP 文档解决了这个问题:

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

于 2013-03-20T21:02:21.977 回答
1

分离自动加载过程!

PHP 是这样工作的:在某些时候,代码执行偶然发现了一个尚未加载的类引用。$obj = new project_one_folder_class()

现在调用注册的自动加载器函数,从第一个添加的函数开始(除非后面添加的函数使用“prepend”参数)。

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

  1. 加载这个类是任务吗?如果没有,什么也不做,让其他函数尝试加载它。
  2. 如果这个函数负责加载类,试着用已知的类名组成一个路径和文件名,并要求这个文件。

第 1 步通常通过查看要加载的类名是否以某个前缀开头来解决。在您的情况下,负责加载以“project_one_”开头的类的自动加载器不应尝试加载以其他内容开头的任何其他类。

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

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

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

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

在每种情况下检查文件是否存在于某个目录中对于性能来说并不是最佳的。您最终将对文件进行大量检查,只需查看类名即可知道您无法加载这些文件。

顺便说一句:Autoloader 函数不需要是单例的。实际上,您的单例实现已损坏且无用。用 实例化自动加载器new,也许将一些配置值传递给构造函数,然后调用spl_autoload_register(),你应该完成了。

于 2013-03-21T01:22:00.697 回答
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,您可以调试是否注册了正确的目录。不需要多个回调,因为您想签入两个目录。

于 2013-03-20T21:25:56.663 回答
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'));

但是,根据您的问题:您可能可以通过使用更灵活的自动加载器来完成同样的事情,请在此处查看我在另一个问题中的答案: wordpress 插件中的类自动加载器

于 2017-08-24T13:05:07.550 回答