如果我正确理解 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的范围限制在特定的上下文中:
return false
对例如名称没有太多某种模式的类)?我知道,我可以向autoload()
函数添加一些条件语句以避免冲突和错误,它看起来效率不高。
谢谢!是的,我很可能只是忽略了一些东西。
按命名空间模仿目录结构:在Wordpress中实际上不可能,是吗?如果你所追求的是某种沟通和逻辑结构,比如必须使用的插件和主题。 (@RoyalBg)
找不到文件:如何确定何时找不到文件“好”,何时找不到文件?通过函数的逻辑?在我看来,减少自动加载器的范围将是更优雅的解决方案。 (@Jon,@ Mark Baker)
但如果我理解你的意见,SPL Autoloader默认情况下会真正应用“全局”。
答案 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;
}
}
这是我经常使用的基本自动加载器,它将名称空间识别为子目录,并且可以提供特定目录以搜索类。