Laravel QueryException绕过try-catch?

时间:2014-06-19 16:51:25

标签: php exception laravel php-5.3 soft-delete

我正在使用Laravel 4和Eloquent ORM。在我的系统中,当有人删除记录时,必须检查它是否有任何相关记录。如果没有,则可以永久删除。但如果确实如此,只需执行softDeletion。

处理这种情况的方法是:尝试强制删除,如果由于引用完整性而抛出异常,则捕获它和softDelete。我知道这看起来很花哨,但是它是由另一位开发人员制作的,我宁愿不要弄乱他的代码。

他所做的是删除,然后如果它抛出异常,只需设置一个标记为" inactivate"记录。它确实运作良好。但是,当我接手时,我实现了softDeleting,使事情变得不那么花哨。

现在,当它尝试强制删除时,它会抛出QueryException,但不会落入catch块。我尝试将Exception更改为\ Exception,QueryException,Illuminate \ Database \ QueryException,但没有成功。有什么想法吗?

更好地说明:

就是这样:

try
{
    $contact->delete();
}
catch(Exception $ex)
{
    $contact->status = 0;
    $contact->save();
    //this works
}

现在就是这样:

protected $softDelete = true;

....

try
{
    $contact->forceDelete();
}
catch(Exception $ex)
{
    $contact->delete();
    //this doesn't work
}

Firebug回复:

{"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}}

这是Illuminate / Database / Eloquent / Builder.php中的forceDelete()函数:

    public function forceDelete()
{
    return $this->query->delete();
}

1 个答案:

答案 0 :(得分:3)

您的$contact->forceDelete();会调用Illuminate\Database\Eloquent\Model中有the following code的方法:

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;
}

现在发生的事情是你的代码在$this->delete();上面会出错并抛出异常。

因此它会到达catch,因此您再次致电$contact->delete();。所以它会得到另一个QueryException,而$this->softDelete没有回到true

您需要做的是设置软删除并尝试再次删除它:

try
{
    $contact->forceDelete();
}
catch(Exception $ex)
{
    $contact->softDelete = true;
    $contact->delete();
}