Laravel 5.1 - 致命错误后未抛出数据库事务异常
Laravel 5.1 - DB transaction exception not thrown after fatal error
我有一个数据库事务,里面有这样一个事件:
DB::beginTransaction();
try {
event(new sendMessage($message, $to, $from));
}
catch(\Exception $e)
{
return 'error';
}
DB::commit();
此事件设置了 2 个工作侦听器;问题是,如果其中一个侦听器出现错误(如果出现问题),例如不正确的变量名,事务的捕获异常 'error' 永远不会 returned,只有实际错误得到已记录,但 'error' 未从交易中 return 编辑。
知道为什么会发生这种情况以及如何解决它,以便如果任何侦听器由于任何原因而失败,则会抛出事务异常吗?
编辑:
所以看起来如果错误是在侦听器中,异常就会被正确抛出。问题似乎是事件构造函数本身是否有错误:
public function __construct(Message $message, $to, $from)
{
$this->messege = $message; //notice the incorrect messege spelling
$this->to = $to;
$this->from = $from;
}
我原以为数据库事务会抛出异常,但它却被记录了下来:
[2015-07-29] local.ERROR: exception 'Symfony\Component\Debug\Exception\FatalErrorException' with message 'Call to a member function message() on null' in */Listeners/Messages/CreateMessage.php:38
其中 CreateMessage.php 是一个使用变量 $message 的侦听器。
class CreateMessage {
public function __construct()
{
//
}
public function handle(sendMessage $event)
{
$event->message->message()->create([ // Exception above get thrown because of the 'messege' typo in the event
'to' => $event->to,
'from' => $event->from
]);
}
}
所以最后一个问题是,如果存在这样的情况,事件侦听器使用的变量名中有拼写错误,我该如何 return 数据库事务错误?
好的。你无法捕获致命错误。继续执行脚本是没有办法的。
因为它们出现后脚本不再执行。
所以你可以理解为:
在这个字符串之后
$event->message->create(
您的代码"not exists"。
还有你的 catch(\Exception $e)
"not exists"。
请参阅此处的 1 16 64 4096 行说明 http://php.net/manual/en/errorfunc.constants.php
在出现致命错误后做某事(但不是你想要的)的唯一方法是使用 register_shutdown_function
并且 laravel 最后要做的就是抛出这个例外
'Symfony\Component\Debug\Exception\FatalErrorException' with message 'Call to a member function message() on null' in */Listeners/Messages/CreateMessage.php:38
但是你无法捕捉到它,之后脚本停止了。
就是这样。
让我们看看我们在 Laravel-core:
中有什么
vendor\laravel\framework\src\Illuminate\Foundation\Bootstrap\HandleExceptions.php
public function bootstrap(Application $app)
{
$this->app = $app;
error_reporting(-1);
set_error_handler([$this, 'handleError']);
set_exception_handler([$this, 'handleException']);
register_shutdown_function([$this, 'handleShutdown']);
if (!$app->environment('testing')) {
ini_set('display_errors', 'Off');
}
}
我们对 register_shutdown_function([$this, 'handleShutdown']);
感兴趣:
/**
* Handle the PHP shutdown event.
*
* @return void
*/
public function handleShutdown()
{
if (!is_null($error = error_get_last()) && $this->isFatal($error['type'])) {
$this->handleException($this->fatalExceptionFromError($error, 0));
}
}
这里我们感兴趣的是$this->fatalExceptionFromError($error, 0)
:
/**
* Create a new fatal exception instance from an error array.
*
* @param array $error
* @param int|null $traceOffset
* @return \Symfony\Component\Debug\Exception\FatalErrorException
*/
protected function fatalExceptionFromError(array $error, $traceOffset = null)
{
return new FatalErrorException(
$error['message'], $error['type'], 0, $error['file'], $error['line'], $traceOffset
);
}
看看这个:
* @return \Symfony\Component\Debug\Exception\FatalErrorException
他们抛出与您收到的完全相同的异常
我有一个数据库事务,里面有这样一个事件:
DB::beginTransaction();
try {
event(new sendMessage($message, $to, $from));
}
catch(\Exception $e)
{
return 'error';
}
DB::commit();
此事件设置了 2 个工作侦听器;问题是,如果其中一个侦听器出现错误(如果出现问题),例如不正确的变量名,事务的捕获异常 'error' 永远不会 returned,只有实际错误得到已记录,但 'error' 未从交易中 return 编辑。
知道为什么会发生这种情况以及如何解决它,以便如果任何侦听器由于任何原因而失败,则会抛出事务异常吗?
编辑:
所以看起来如果错误是在侦听器中,异常就会被正确抛出。问题似乎是事件构造函数本身是否有错误:
public function __construct(Message $message, $to, $from)
{
$this->messege = $message; //notice the incorrect messege spelling
$this->to = $to;
$this->from = $from;
}
我原以为数据库事务会抛出异常,但它却被记录了下来:
[2015-07-29] local.ERROR: exception 'Symfony\Component\Debug\Exception\FatalErrorException' with message 'Call to a member function message() on null' in */Listeners/Messages/CreateMessage.php:38
其中 CreateMessage.php 是一个使用变量 $message 的侦听器。
class CreateMessage {
public function __construct()
{
//
}
public function handle(sendMessage $event)
{
$event->message->message()->create([ // Exception above get thrown because of the 'messege' typo in the event
'to' => $event->to,
'from' => $event->from
]);
}
}
所以最后一个问题是,如果存在这样的情况,事件侦听器使用的变量名中有拼写错误,我该如何 return 数据库事务错误?
好的。你无法捕获致命错误。继续执行脚本是没有办法的。 因为它们出现后脚本不再执行。 所以你可以理解为:
在这个字符串之后
$event->message->create(
您的代码"not exists"。
还有你的 catch(\Exception $e)
"not exists"。
请参阅此处的 1 16 64 4096 行说明 http://php.net/manual/en/errorfunc.constants.php
在出现致命错误后做某事(但不是你想要的)的唯一方法是使用 register_shutdown_function
并且 laravel 最后要做的就是抛出这个例外
'Symfony\Component\Debug\Exception\FatalErrorException' with message 'Call to a member function message() on null' in */Listeners/Messages/CreateMessage.php:38
但是你无法捕捉到它,之后脚本停止了。 就是这样。
让我们看看我们在 Laravel-core:
中有什么vendor\laravel\framework\src\Illuminate\Foundation\Bootstrap\HandleExceptions.php
public function bootstrap(Application $app)
{
$this->app = $app;
error_reporting(-1);
set_error_handler([$this, 'handleError']);
set_exception_handler([$this, 'handleException']);
register_shutdown_function([$this, 'handleShutdown']);
if (!$app->environment('testing')) {
ini_set('display_errors', 'Off');
}
}
我们对 register_shutdown_function([$this, 'handleShutdown']);
感兴趣:
/**
* Handle the PHP shutdown event.
*
* @return void
*/
public function handleShutdown()
{
if (!is_null($error = error_get_last()) && $this->isFatal($error['type'])) {
$this->handleException($this->fatalExceptionFromError($error, 0));
}
}
这里我们感兴趣的是$this->fatalExceptionFromError($error, 0)
:
/**
* Create a new fatal exception instance from an error array.
*
* @param array $error
* @param int|null $traceOffset
* @return \Symfony\Component\Debug\Exception\FatalErrorException
*/
protected function fatalExceptionFromError(array $error, $traceOffset = null)
{
return new FatalErrorException(
$error['message'], $error['type'], 0, $error['file'], $error['line'], $traceOffset
);
}
看看这个:
* @return \Symfony\Component\Debug\Exception\FatalErrorException
他们抛出与您收到的完全相同的异常