spl_autoload:限制范围

时间:2014-05-05 10:18:17

标签: php wordpress autoload spl-autoload-register

如果我正确理解 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. 更聪明的东西?
  4. 我知道,我可以向autoload()函数添加一些条件语句以避免冲突和错误,它看起来效率不高。

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

    修改

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

    找不到文件:如何确定何时找不到文件“好”,何时找不到文件?通过函数的逻辑?在我看来,减少自动加载器的范围将是更优雅的解决方案。 (@Jon,@ Mark Ba​​ker)

    但如果我理解你的意见,SPL Autoloader默认情况下会真正应用“全局”。

1 个答案:

答案 0 :(得分:1)

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

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

SPL将一个接一个地完成这些注册功能。首先是functionA,然后是functionB,如果请求的类没有通过functionA加载。

编辑:     

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

}

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