Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/267.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 为未知类调用静态方法不会';无法在自动加载中触发异常捕获_Php - Fatal编程技术网

Php 为未知类调用静态方法不会';无法在自动加载中触发异常捕获

Php 为未知类调用静态方法不会';无法在自动加载中触发异常捕获,php,Php,由于某些原因,在尝试对尚不存在的类(PHP5.3.9)调用静态方法时,\uuu autoload函数中抛出的异常不会被捕获 请参见此示例代码: <?php function __autoload($class) { throw new Exception('loaded ' . $class . "\n"); } try { echo "Object: "; $test = new Log(); } catch (Exception $e) { erro

由于某些原因,在尝试对尚不存在的类(PHP5.3.9)调用静态方法时,
\uuu autoload
函数中抛出的异常不会被捕获

请参见此示例代码:

<?php
function __autoload($class)
{
    throw new Exception('loaded ' . $class . "\n");
}


try {
    echo "Object: ";
    $test = new Log();
}
catch (Exception $e)
{
    error_log($e->getMessage());
}

// Exception is caught with static var.
try {
    echo "Static var: ";
    Log::$blah;
}
catch (Exception $e)
{
    error_log($e->getMessage());
}

// Fatal error occures with static method.
try {
    echo "Static method: ";
    Log::blah();
}
catch (Exception $e)
{
    error_log($e->getMessage());
}

PHP混合了错误和异常。在这种情况下,在捕获异常之前“抛出”致命错误。这是关于优先事项。调用未定义的函数并给出致命错误比处理异常具有更高的优先级,因为代码已经停止()。致命错误本身无法被捕获

由于无法使用
try
/
catch
块捕获致命错误,因此脚本将在致命错误处停止

对于已定义类的未定义静态属性也是如此。这将触发一个致命的错误,以及你将无法捕捉

但是,您可以将错误转换为异常并捕获这些异常,但是这不适用于致命错误()。我假设这是您遇到的根限制:致命错误会导致脚本执行下降,无论它是否出现在
try
/
catch
块中。异常处理也会停止

此外,PHP5.5.0-dev和PHP5.4.0beta2-dev还提供了一个与您的代码示例类似的示例。这让我相信,在即将发布的PHP版本中,会有一个可以被视为缺陷的bug。在PHP5.4中报告这一点可能是值得的


另请参见在没有
\uuu自动加载开销的情况下说明问题的部分。是的,PHP在自动加载中抛出异常时会出现问题。
但你可以使用一个有趣的技巧:

function __autoload($class)
{
    eval("class $class {            
        static function __callStatic(\$name,\$val){
            throw new Exception('Loaded ' . $class . PHP_EOL); 
        }         
    }");    
    throw new Exception('Loaded ' . $class . PHP_EOL);
}

不要忘记在evaled表达式中实现名称空间工作。

当发生致命错误时,您收到的日志/调试输出是什么?FWIW,是您在
\uuuu autoload
中抛出异常导致了问题,坦率地说,这不是PHP所期望的。你真的需要这么做吗?我能闻到PHP的错误,不是吗?我可以复制它。它进入自动加载,但无法抛出异常。无论如何,重复:@RobAgar我不同意。当然,异常的消息是错误的,它应该是:“未能加载$class”。PHP手册中有一个以同样方式构造的示例,只是为了演示您可以在自动加载(示例3)中抛出异常。@Palantir确实如此。感觉不对,但我想这可能有用。但是,是的,PHP错误。只是好奇,这个名称空间在求值表达式中会是什么样子?不要忘记,这只会将致命错误转移到访问未定义静态属性的位置,即
Log::$blah在问题中。这似乎是对你的自动加载功能的一个非常讨厌的攻击。我只是问为什么会发生这种情况:)Hakre,这不会将致命错误向上移动,这将防止致命错误并将正常异常向上移动,直到访问未定义的静态属性为止。但是,如果稍后(自动加载失败后)尝试在代码中的某个位置创建此类的实例,则需要实现_构造,该构造将在evaled表达式中引发相同的异常或者日志::$blah并注释抛出的异常u autoload,您仍然会得到一个致命错误。那么,为什么仅调用未定义类的静态方法对于致命错误的优先级高于异常处理的优先级呢?我想这确实是PHP中的一个bug?@bartzy:当然,致命错误与异常完全无关。这正是重点。也许我应该在前面用粗体字写出来?@hakre:我编辑了我最后的评论,并对我的意思做了解释。我认为这是一个PHP错误,而不是可以用这是一个致命错误这一事实来解释的常规错误。静态方法示例上面的两个示例也生成了致命错误。只是在此之前捕获了异常并阻止了致命错误的发生。这不可能是一个bug。您在这里做不同的事情,而这些不同的事情是由脚本引擎以不同的方式完成的(因为它们是不同的事情)。在前两种(不同)情况下,在触发致命错误之前(
new Log
Log::$blah
),会触发异常并阻止触发致命错误。但是对于函数调用,不管您在autoload中抛出异常,都会触发致命错误。异常不会停止PHP以触发致命错误。对于前两个示例,实际上没有创建致命错误。@hakre:为什么只有在第三个示例中,无论发生什么,都会触发致命错误?是不是因为PHP认为调用静态方法的行为应该与调用静态属性或新对象的行为不同?