Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/230.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 为什么';无法从_toString()引发异常?_Php_Exception - Fatal编程技术网

Php 为什么';无法从_toString()引发异常?

Php 为什么';无法从_toString()引发异常?,php,exception,Php,Exception,为什么无法从_toString()抛出异常 上面的代码生成以下内容: Fatal error: Method a::__toString() must not throw an exception in /var/www/localhost/htdocs/index.php on line 12 我被指到了描述这种行为的地方,但为什么?有什么理由这样做吗 这里有人知道吗 在bug跟踪器上,php开发团队像往常一样除了看手册外什么也没说:我猜\uuu-toString是黑客的,因此存在于典型堆栈

为什么无法从_toString()抛出异常

上面的代码生成以下内容:

Fatal error: Method a::__toString() must not throw an exception in /var/www/localhost/htdocs/index.php on line 12
我被指到了描述这种行为的地方,但为什么?有什么理由这样做吗

这里有人知道吗


在bug跟踪器上,php开发团队像往常一样除了看手册外什么也没说:

我猜
\uuu-toString
是黑客的,因此存在于典型堆栈之外。那么,抛出的异常将不知道去哪里。

我认为这一决定的理由从未公开过。看起来有一些内部架构限制


在更抽象的层面上,这有点道理。对象应该能够返回其自身的字符串表示形式,没有任何原因导致此类操作失败。

经过几次搜索后,我发现了以下内容:

Johannes解释说,无法确保Zend引擎能够正确处理转换到字符串期间引发的异常,,除非重写引擎的大部分内容,否则这不会改变。他补充说,过去曾就此类问题进行过讨论,并建议Guilherme检查档案

上面提到的是PHP5.3发行版管理器,因此它可能是一个“官方”解释,正如您可能会发现的那样,它解释了为什么PHP会以这种方式运行

本节接着提到:

\uuuuToString()
会,奇怪的是,接受


因此,在
\uu-toString()

中的错误报告方面,并不是所有内容都丢失了。作为对公认答案的回应,我提出了一种(也许)更好的方法来处理
\uu-toString()中的异常

这假设定义了一个异常处理程序,大多数框架都是这样。与
trigger\u error
方法一样,这样做将违背try..catch的目的,但仍然比使用
echo
转储输出要好得多。此外,许多框架将错误转换为异常,因此
trigger\u error
无论如何都无法工作

作为额外的好处,您将获得一个完整的堆栈跟踪,就像您选择的框架的正常异常和正常的开发人员生产行为一样

在Laravel中工作得非常好,我非常确定它在几乎所有现代PHP框架中都能工作

相关屏幕截图:
注意:在本例中,
output()
\uu toString()
方法调用


我找到了一个简单的解决方案:

当发生到字符串的错误转换时,只需返回类似于非字符串类型in _toString的内容:NULL、FALSE甚至异常

这将导致如下输出(在php-交互式SHELL中):


从php 7.4开始,似乎允许从_toString()引发异常。我做了一个php7.2兼容性检查,它这样说,并指出了原则和方法


请查找有关建议的更多信息

“对象应该能够返回其自身的字符串表示形式,没有任何理由导致此类操作失败。”呵呵:-)echo$a->uu toString();抛出它;-)这是意料之中的。在这种情况下,方法也应该能够返回一些强制转换为字符串的内容,但是不,我们得到的是未处理的异常。您得到的异常不是从
\uu toString()
中抛出的,但我的意思是“对象应该能够返回自身的字符串表示形式”对于“方法应该能够返回要回显的内容”也应该为true正如你提到的。但这是假的。ps:我得到的异常是从uuToString()类a{public function uuToString(){throw new exception();}}}$a=new a()引发的;echo$a->_toString();呵呵?当对象不存在时,它是一个致命错误(请注意),而不是一个错误exception@zerkms这是因为直接调用它是好的,它存在于正常调用过程的范围内,而ToString可以在其他事物的中间被调用(任何时候你需要一个字符串并通过一个对象)。处理异常需要做大量的工作,以确保异常可以在引擎中的任何一点处理,而不是像现在这样在方法调用边界上处理。嘿,thanx。但是trigger_error()不能仅仅因为try/catch是全局的,try/catch是具体的而取代它。@zerkms-没错,它不是替代品。如果有足够多的人发表意见,也许他们会重写Zend引擎此外,许多框架捕获错误并将其作为异常重新抛出——这会带来完全相同的问题。这值得一大关注事实上,如果您显式调用u-toString(),那么echo$a->u-toString();将成功地将异常作为致命错误传递,其中echo$a;不会。特别是因为
echo$a->\uuuu-toString()
可以引发异常,但
echo$a
不能。uuuu-toString不是黑客行为,它是提供对象字符串表示的完全标准方式。(string)$a和$a->\uuuu toString()之间的区别在于引擎处理调用的方式,这与$x->something和$x->\uuu调用(“something”)之间的区别相同。一个是直接调用对象中的函数(一个恰好以_u开头的函数),另一个是Zend引擎内部处理的神奇方法。@Sprog我认为应用了hackish术语,它的实现是hackish。它的工作对我来说:当在_u-toString中得到致命错误时,它是不需要的。然后可以处理可捕获的致命错误,而不是只在\uuuToStringi中获取致命错误。我不确定您是否阅读了该问题。只是想提醒您:我问过为什么不可能这样做。PHP 7.4现在在
\uuu toString()
Fatal error: Method a::__toString() must not throw an exception in /var/www/localhost/htdocs/index.php on line 12
public function __toString()
{
    try {
        // ... do some stuff
        // and try to return a string
        $string = $this->doSomeStuff();
        if (!is_string($string)) {
            // we must throw an exception manually here because if $value
            // is not a string, PHP will trigger an error right after the
            // return statement, thus escaping our try/catch.
            throw new \LogicException(__CLASS__ . "__toString() must return a string");
        }

        return $string;
    } catch (\Exception $exception) {
        $previousHandler = set_exception_handler(function (){
        });
        restore_error_handler();
        call_user_func($previousHandler, $exception);
        die;
    }
}
Catchable fatal error: Method MyClass::__toString() must return a string value in php shell code on line 1