duanlan7903 2014-05-05 10:18
浏览 22

spl_autoload:限制范围

If I get the behaviour of SPL Autoloader correctly, it acts in a "global scope", right? If we have, say, this code:

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

... it applies to the rest of the application OR if hooked to Wordpress action, from the hook onwards, right?

It just seems to me that it is not very convenient, especially if you work in the frame of larger frameworks (such as Wordpress). Is there way, how to limit the scope of SPL Autoload to specific context by:

  1. defining the SPL Autoload different way?
  2. having something specific in the function (such as return false on e.g. classes which names does not much some sort of pattern)?
  3. something more clever?

I know, that I can add some conditional statements to autoload() function to avoid conflicts and errors, it just does not seem very efficient.

Thanks! And yes, it is very possible that I'm just overlooking something.

Edit

Mimicing directory structure by namespaces: It's not actually possible within Wordpress, is it? If what you're after is some sort of communication and logical structure between, say, must-use plugins and themes. (@RoyalBg)

Not finding a file: How to determine than when it is "okay" to not finding a file and when it is not? By logic of the function? It still seems to me, that reducing the scope of autoloader would be way more elegant sollution. (@Jon, @Mark Baker)

But if I understand your comments well, SPL Autoloader truly applies "globally" by default.

  • 写回答

1条回答 默认 最新

  • douhuifen9942 2014-05-05 10:34
    关注

    You can register multiple autoloader function/methods. SPL will go through them all until the desired class is loaded.

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

    SPL will go through these registered functions, one after the other. At first functionA, then functionB, if the requested class is not loaded via functionA.

    EDIT:

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

    This is my basic autoloader i use very often, it recognizes namespaces as subdirectories and can be fed with specific directories where to search for classes.

    评论

报告相同问题?

悬赏问题

  • ¥15 基于卷积神经网络的声纹识别
  • ¥15 Python中的request,如何使用ssr节点,通过代理requests网页。本人在泰国,需要用大陆ip才能玩网页游戏,合法合规。
  • ¥100 为什么这个恒流源电路不能恒流?
  • ¥15 有偿求跨组件数据流路径图
  • ¥15 写一个方法checkPerson,入参实体类Person,出参布尔值
  • ¥15 我想咨询一下路面纹理三维点云数据处理的一些问题,上传的坐标文件里是怎么对无序点进行编号的,以及xy坐标在处理的时候是进行整体模型分片处理的吗
  • ¥15 CSAPPattacklab
  • ¥15 一直显示正在等待HID—ISP
  • ¥15 Python turtle 画图
  • ¥15 stm32开发clion时遇到的编译问题