Laravel QueryException 绕过 try-catch?

Posted

技术标签:

【中文标题】Laravel QueryException 绕过 try-catch?【英文标题】:Laravel QueryException bypassing try-catch? 【发布时间】:2014-08-10 07:38:01 【问题描述】:

我正在使用 Laravel 4 和 Eloquent ORM。在我的系统中,当有人删除一条记录时,它必须检查它是否有任何关联的记录。如果没有,那么它可能会被永久删除。但如果是这样,只需执行一次 softDeletion。

这种情况的处理方式是:尝试强制删除,如果因为参照完整性而抛出异常,捕获它并软删除。我知道这看起来很花哨,但它是由另一个开发人员制作的,我不想弄乱他的代码。

他所做的是删除,然后如果它抛出异常,只需设置一个标志以“停用”记录。它确实运作良好。然而,当我接手时,我实施了 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

萤火虫回应:

"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();

【问题讨论】:

如果您使用的是 Laravel 4.2,软删除的工作方式已经改变 - 请参阅此处:laravel.com/docs/upgrade。但如果你不是,那恐怕我不知道原因。 让它抛出一个异常,它应该告诉你它抛出了什么异常。应该只是能够复制和粘贴。 不。这是 Laravel 4.1。不过感谢您的帮助! @user3158900 对不起,我不明白。你能说得更具体点吗? 运行它,然后它应该在浏览器中输出错误页面,并且错误页面应该包含抛出的异常。您应该能够将其复制并粘贴到 Exception 所在的代码中。例如,在此页面 filp.github.io/whoops/demo 上显示 RuntimeException,因此您可以在 try/catch 块中使用 catch(RuntimeException) 捕获它。您是否也可以发布您的forceDelete() 函数,也许存在引发这些异常的潜在问题。如果查询是错误的,这无论如何都无关紧要。 【参考方案1】:

您的$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();

【讨论】:

以上是关于Laravel QueryException 绕过 try-catch?的主要内容,如果未能解决你的问题,请参考以下文章

php Laravel [Illuminate\Database\QueryException]

Connection.php 第 729 行中的 QueryException:SQLSTATE[23000]:Laravel 5.2

Laravel 8 - 找不到驱动程序:Illuminate\Database\QueryException 找不到驱动程序(SQL:select * from `list`)

如何绕过 Laravel 5 维护模式的一些 IP 地址

laravel使用队列

Laravel 迁移 Postgres 错误