Laravel QueryException 绕过 try-catch?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24312132/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Laravel QueryException bypassing try-catch?
提问by Gustavo Silva
I am using Laravel 4, and the Eloquent ORM. In my system, when someone deletes a record, it has to check if it has any associated records. If it doesn't, then it may be deleted permanently. But if it does, just perform a softDeletion.
我正在使用 Laravel 4 和 Eloquent ORM。在我的系统中,当有人删除一条记录时,它必须检查它是否有任何关联的记录。如果没有,那么它可能会被永久删除。但如果是这样,只需执行 softDeletion。
The way that this situation is being handled is: try to forceDelete, and if it throws an Exception because of the referential integrity, catch it and softDelete. I know this looks gimmicky, but it was made by another developer and I'd rather not mess with his code.
这种情况的处理方式是:尝试forceDelete,如果它因为引用完整性而抛出异常,则捕获它并使用softDelete。我知道这看起来很花哨,但它是由另一个开发人员制作的,我不想弄乱他的代码。
What he did was to delete, then if it threw an Exception, just set a flag to "inactivate" the record. It did work well. However, when I took over I implemented softDeleting to make things less gimmicky.
他所做的是删除,然后如果它抛出异常,只需设置一个标志来“停用”记录。它工作得很好。然而,当我接手时,我实施了 softDeleting 来让事情变得不那么花哨。
Now, when it tries to forceDelete,it throws the QueryException but doesn't fall into the catch block. I've tried changing Exception to \Exception, QueryException, Illuminate\Database\QueryException, but no success. Any ideas?
现在,当它尝试强制删除时,它会抛出 QueryException 但不会落入 catch 块。我尝试将异常更改为 \Exception、QueryException、Illuminate\Database\QueryException,但没有成功。有任何想法吗?
To illustrate it better:
为了更好地说明它:
It was like this:
它是这样的:
try
{
$contact->delete();
}
catch(Exception $ex)
{
$contact->status = 0;
$contact->save();
//this works
}
And now it is like this:
现在是这样的:
protected $softDelete = true;
....
try
{
$contact->forceDelete();
}
catch(Exception $ex)
{
$contact->delete();
//this doesn't work
}
Firebug response:
萤火虫反应:
{"error":{"type":"Illuminate\Database\QueryException","message":"SQLSTATE[23000]: Integrity constraint violation: 1451
Cannot delete or update a parent row: a foreign key constraint fails (`tst_db\/contact_company`, CONSTRAINT `fk_contact_company_contacts_id`
FOREIGN KEY (`contact_id`) REFERENCES `contacts` (`id`) ON DELETE NO ACTION ON UPDATE CASCADE)
(SQL: delete from `contacts` where `id` = 28)","file":"\/Applications\/XAMPP\/xamppfiles\/htdocs\/application\/vendor\/laravel\/framework\/src\/Illuminate\/Database\/Connection.php","line":555}}
This is the forceDelete() function from Illuminate/Database/Eloquent/Builder.php:
这是 Illuminate/Database/Eloquent/Builder.php 中的 forceDelete() 函数:
public function forceDelete()
{
return $this->query->delete();
}
采纳答案by Unnawut
Your $contact->forceDelete();
will call the method in Illuminate\Database\Eloquent\Model
which has the following code:
您$contact->forceDelete();
将调用Illuminate\Database\Eloquent\Model
具有以下代码的方法:
public function forceDelete()
{
$softDelete = $this->softDelete;
// We will temporarily disable false delete to allow us to perform the real
// delete operation against the model. We will then restore the deleting
// state to what this was prior to this given hard deleting operation.
$this->softDelete = false;
$this->delete();
$this->softDelete = $softDelete;
}
Now what happen is your code will error on $this->delete();
above and throw an exception.
现在发生的情况是您的代码将在$this->delete();
上面出错并引发异常。
So it reaches your catch
, and so you call $contact->delete();
once more. So it gets another QueryException
, without $this->softDelete
ever set back to true
.
所以它到达你的catch
,所以你$contact->delete();
再次调用。所以它得到了另一个QueryException
,$this->softDelete
从来没有退缩过true
。
What you need to do is set soft delete back and try delete it again:
您需要做的是重新设置软删除并再次尝试删除它:
try
{
$contact->forceDelete();
}
catch(Exception $ex)
{
$contact->softDelete = true;
$contact->delete();
}