Php 在SPL自动加载程序中引发异常?
在PHP中,有没有一种方法可以在SPL自动加载程序失败时抛出异常?它在PHP5.2.11下似乎不起作用Php 在SPL自动加载程序中引发异常?,php,spl,Php,Spl,在PHP中,有没有一种方法可以在SPL自动加载程序失败时抛出异常?它在PHP5.2.11下似乎不起作用 class SPLAutoLoader{ public static function autoloadDomain($className) { if(file_exists('test/'.$className.'.class.php')){ require_once('test/'.$className.'.class.php');
class SPLAutoLoader{
public static function autoloadDomain($className) {
if(file_exists('test/'.$className.'.class.php')){
require_once('test/'.$className.'.class.php');
return true;
}
throw new Exception('File not found');
}
} //end class
//start
spl_autoload_register( array('SPLAutoLoader', 'autoloadDomain') );
try{
$domain = new foobarDomain();
}catch(Exception $c){
echo 'File not found';
}
当调用上面的代码时,没有异常的迹象,相反,我得到了一个标准的“致命错误:在bla中找不到类'foobarDomain'。脚本的执行将终止。根据中的注释,可以从自动加载程序调用另一个函数,而自动加载程序将引发异常
class SPLAutoLoader{
public static function autoloadDomain($className) {
if(file_exists('test/'.$className.'.class.php')){
require_once('test/'.$className.'.class.php');
return true;
}
self::throwFileNotFoundException();
}
public static function throwFileNotFoundException()
{
throw new Exception('File not found');
}
} //end class
//start
spl_autoload_register( array('SPLAutoLoader', 'autoloadDomain') );
try{
$domain = new foobarDomain();
}catch(Exception $c){
echo 'File not found';
}
这不是一个bug,而是:
注意:在自动加载
功能中抛出的异常无法在捕获
块中捕获,并导致致命错误
原因是可能有多个自动加载处理程序,在这种情况下,您不希望第一个处理程序抛出异常并绕过第二个处理程序。您希望第二个处理程序有机会自动加载其类。如果您使用的库使用自动加载功能,您不希望它绕过自动加载处理程序,因为它们在自动加载程序中抛出异常
如果要检查是否可以实例化一个类,则使用并传递true
作为第二个参数(或者不使用它,true
是默认参数):
这里是一个成熟的factory对象,它演示了自动加载、名称空间支持、来自非静态实例(具有可变路径)的可调用性、加载错误和自定义异常的处理
abstract class AbstractFactory implements \ArrayAccess
{
protected $manifest;
function __construct($manifest)
{
$this->manifest = $manifest;
}
abstract function produce($name);
public function offsetExists($offset)
{
return isset($this->manifest[$offset]);
}
public function offsetGet($offset)
{
return $this->produce($offset);
}
//implement stubs for other ArrayAccess funcs
}
abstract class SimpleFactory extends AbstractFactory {
protected $description;
protected $path;
protected $namespace;
function __construct($manifest, $path, $namespace = "jj\\") {
parent::__construct($manifest);
$this->path = $path;
$this->namespace = $namespace;
if (! spl_autoload_register(array($this, 'autoload'), false)) //throws exceptions on its own, but we want a custom one
throw new \RuntimeException(get_class($this)." failed to register autoload.");
}
function __destruct()
{
spl_autoload_unregister(array($this, 'autoload'));
}
public function autoload($class_name) {
$file = str_replace($this->namespace, '', $class_name);
$filename = $this->path.$file.'.php';
if (file_exists($filename))
try {
require $filename; //TODO add global set_error_handler and try clause to catch parse errors
} catch (Exception $e) {} //autoload exceptions are not passed by design, nothing to do
}
function produce($name) {
if (isset($this->manifest[$name])) {
$class = $this->namespace.$this->manifest[$name];
if (class_exists($class, $autoload = true)) {
return new $class();
} else throw new \jj\SystemConfigurationException('Factory '.get_class($this)." was unable to produce a new class {$class}", 'SYSTEM_ERROR', $this);
//an example of a custom exception with a string code and data container
} else throw new LogicException("Unknown {$this->description} {$name}.");
}
function __toString() //description function if custom exception class wants a string explanation for its container
{
return $this->description." factory ".get_class($this)."(path={$this->path}, namespace={$this->namespace}, map: ".json_encode($this->manifest).")";
}
}
最后是一个例子:
namespace jj;
require_once('lib/AbstractFactory.php');
require_once('lib/CurrenciesProvider.php'); //base abstract class for all banking objects that are created
class CurrencyProviders extends SimpleFactory
{
function __construct()
{
$manifest = array(
'Germany' => 'GermanBankCurrencies',
'Switzerland' => 'SwissBankCurrencies'
);
parent::__construct($manifest, __DIR__.'/CurrencyProviders/', //you have total control over relative or absolute paths here
'banks\');
$this->description = 'currency provider country name';
}
}
现在做
$currencies_cache = (new \jj\CurrencyProviders())['Germany'];
或
LogicException(“未知货币供应国名称乌克兰”)
如果/CurrencyProviders/中没有SwissCurrencies.php文件
\jj\SystemConfigurationException('Factory jj\CurrencyProviders无法生成新类banks\SwissCurrences。调试数据:货币提供程序国家名称Factory jj\CurrencyProviders(路径=/var/www/hosted/site/../CurrencyProviders/,命名空间=banks\,映射:{“德国”:“德国银行货币”,“瑞士”:“瑞士银行货币”})
只要付出足够的努力,这个工厂就可以扩展到捕获解析错误()并将参数传递给构造函数。到底发生了什么?您只说它失败了,但没有说它是如何失败的。调用上述代码时,没有异常迹象,相反,我得到了一个标准的“致命错误:在bla中找不到类'foobarDomain'”。并且脚本的执行终止。太好了,谢谢。在包含之前,当您首先在函数中抛出异常时会发生什么?似乎我发现了另一个PHP错误。不幸的是,这不起作用。相同的错误,没有抛出异常:(非常感谢您——您挽救了这一天!这种行为在PHP5.3中发生了更改-异常现在可以在自动加载器中抛出和捕获。但是,如果您注册了多个自动加载器,则需要小心。
$currencies_cache = (new \jj\CurrencyProviders())['Germany'];
$currencies_cache = (new \jj\CurrencyProviders())['Ukraine'];