0

如果我正确理解了SPL Autoloader的行为,它会在“全局范围”中起作用,对吗?如果我们有,比如说,这段代码:

class Autoloader {

    protected static $instance = NULL;

    public static function get_instance() {
        NULL === self::$instance and self::$instance = new self;
        return self::$instance;
    }

    public function init() {
        spl_autoload_register(array($this,'autoload'));
    }

    private function autoload() {
        // to the autoload magic
    }

}

$autoloader = new Autoloader();
$autoloader->init();

// or

add_action('muplugins_loaded', array(Autoloader::get_instance(),'init'));

...它适用于应用程序的其余部分,或者如果挂钩到 Wordpress 操作,从挂钩开始,对吗?

在我看来,这不是很方便,特别是如果您在较大框架(例如 Wordpress)的框架中工作。有没有办法,如何通过以下方式将 SPL Autoload 的范围限制在特定的上下文中:

  1. 以不同的方式定义 SPL Autoload?
  2. 在函数中有一些特定的东西(例如return false在名称没有多少某种模式的类上)?
  3. 更聪明的东西?

我知道,我可以添加一些条件语句来autoload()避免冲突和错误,但这似乎不是很有效。

谢谢!是的,我很可能只是忽略了一些东西。

编辑

通过命名空间模拟目录结构:在 Wordpress 中实际上是不可能的,是吗?如果你追求的是某种沟通和逻辑结构,比如说,必须使用的插件主题。(@RoyalBg)

找不到文件:如何确定什么时候找不到文件“可以”,什么时候不可以?通过函数的逻辑?在我看来,缩小自动加载器的范围将是更优雅的解决方案。(@乔恩,@马克贝克)

但是,如果我很好地理解了您的评论,SPL Autoloader 在默认情况下真正适用于“全局”。

4

1 回答 1

1

您可以注册多个自动加载器功能/方法。SPL 将遍历它们,直到加载所需的类。

<?php
function loaderA($name) { // Do Stuff }
function loaderB($name) { // Do Other Stuff }
spl_autoload_register('functionA');
spl_autoload_register('functionB');
?>

SPL 会一个接一个地遍历这些注册函数。如果请求的类不是通过函数A加载的,则首先是函数A,然后是函数B。

编辑:

final class LoaderException extends \Exception{}

class Loader {

    /**
     * Project-Root-Directory
     * @var string
     */
    protected static $AbsPath;
    /**
     * Directory-List
     * @var array
     */
    protected static $DirList;

    /**
     * DO NOT INSTANTIATE
     */
    private function __construct() {}

    /**
     * The actual autoloader.
     * @param string $name Class-Name
     * @return void
     * @throws LoaderException
     */
    public static function load($name) {
        if(!is_string($name))
            throw new \InvalidArgumentException('Argument is not a string.');
        $a = isset(static::$AbsPath) ? static::$AbsPath : '';
        $f = str_replace('\\', '/', $name).'.php';
        if(!is_array(static::$DirList)) {
            if(file_exists($a.$f))
                return include $a.$f;
            if(file_exists(getcwd().$f))
                return include getcwd().$f;
            throw new LoaderException('Unable to load "'.$name.'".');
        }
        foreach(static::$DirList as $d) {
            if(file_exists($a.$d.$f))
                return include $a.$d.$f;
        }
        throw new LoaderException('Unable to load "'.$name.'".');
    }

    /**
     * Registers the Loader.
     */
    public static function register() {
        spl_autoload_register(__CLASS__.'::load');
    }

    /**
     * Unregisters the Loader.
     */
    public static function unregister() {
        spl_autoload_unregister(__CLASS__.'::load');
    }

    /**
     * Adds one, or more, directories to the Directory-List.
     * @throws LoaderException
     */
    public static function addDir() {
        foreach(func_get_args() as $k => $v) {
            if(!is_string($v))
                throw new \InvalidArgumentException('Argument #'.($k+1).' is not a string.');
            if(!is_dir($v))
                throw new \InvalidArgumentException('Argument #'.($k+1).' is not a directory.');
            if(!is_array(static::$DirList) or !in_array($v, static::$DirList))
                static::$DirList[] = $v;
        }
    }

    /**
     * Removes one, or more, directories from the Directory-List.
     * @throws LoaderException
     */
    public static function removeDir() {
        foreach(func_get_args() as $k => $v) {
            if(!is_string($v))
                throw new \InvalidArgumentException('Argument #'.($k+1).' is not a string.');
            if(in_array($v, static::$DirList))
                unset(static::$DirList[array_search($v, static::$DirList)]);
        }
    }

    /**
     * Sets the Absolute-Path for the loader, this will speed up the loading process.
     * @param string $path Absolute-Path to the Project root directory
     * @throws LoaderException
     */
    public static function setAbsPath($path = null) {
        if(isset($path)) {
            if(!is_string($path))
                throw new \InvalidArgumentException('Argument is not a string.');
            if(!is_dir($path))
                throw new \InvalidArgumentException('Invalid path "'.$path.'".');
        }
        static::$AbsPath = $path;
    }

}

这是我经常使用的基本自动加载器,它将命名空间识别为子目录,并且可以提供搜索类的特定目录。

于 2014-05-05T10:34:55.327 回答