记 Laravel 模型 deleted 事件未被触发领悟

给模型绑定了观察器,注册了deleted事件,预计以下代码会被触发

User::where('id', 1)->delete();

然而理想是美好的,现实是残酷的,仔细检查了流程, 感觉Perfect,最终几经波折找到如下攻略
file
总结如下
敲黑板! 检索了模型实例的操作才会被触发

// 这样是不行的
User::where('id', 1)->delete();
// 这样是可行的
$user = User::find(1);
$user->delete();
// 或者
User::destroy(1);
User::destroy([1, 2]);

还是文档啃少了!

本作品采用《CC 协议》,转载必须注明作者和本文链接
你迷茫的原因大多数是因为,想得多,做得少
本帖由系统于 7年前 自动加精
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
讨论数量: 9
$user = User::find(1);
$user->delete();

这个是调用 \Illuminate\Database\Eloquent\Model:delete() 方法,源码里写了会在 delete 前后触发 deletingdeleted 事件,源码是:

public function delete()
    {
        if (is_null($this->getKeyName())) {
            throw new Exception('No primary key defined on model.');
        }

        // If the model doesn't exist, there is nothing to delete so we'll just return
        // immediately and not do anything else. Otherwise, we will continue with a
        // deletion process on the model, firing the proper events, and so forth.
        if (! $this->exists) {
            return;
        }

        if ($this->fireModelEvent('deleting') === false) {
            return false;
        }

        // Here, we'll touch the owning models, verifying these timestamps get updated
        // for the models. This will allow any caching to get broken on the parents
        // by the timestamp. Then we will go ahead and delete the model instance.
        $this->touchOwners();

        $this->performDeleteOnModel();

        // Once the model has been deleted, we will fire off the deleted event so that
        // the developers may hook into post-delete operations. We will then return
        // a boolean true as the delete is presumably successful on the database.
        $this->fireModelEvent('deleted', false);

        return true;
    }

User::where('id', 1)->delete();

调用的是 Illuminate\Database\Eloquent\Builder::delete(),然后调用 Illuminate\Database\Query\Builder::delete() ,源码里没有加上事件,直接删除数据了,Illuminate\Database\Query\Builder::delete() 源码是:

public function delete($id = null)
    {
        // If an ID is passed to the method, we will set the where clause to check the
        // ID to let developers to simply and quickly remove a single row from this
        // database without manually specifying the "where" clauses on the query.
        if (! is_null($id)) {
            $this->where($this->from.'.id', '=', $id);
        }

        return $this->connection->delete(
            $this->grammar->compileDelete($this), $this->cleanBindings(
                $this->grammar->prepareBindingsForDelete($this->bindings)
            )
        );
    }

文档仅是源码的介绍,还得看源码怎么写的。。

7年前 评论
free-andy

@lx1036 感觉现在看源码还有点吃力,把使用搞流畅了,下一步就是源码了

7年前 评论

@free-andy 是,这些还是靠多找文章看多实践,都是这么过来的。

7年前 评论

如果需要通过非主键检索并删除数据,怎么样才能触发删除事件呢?

7年前 评论
free-andy

@messikiller 这种批量删除,可以考虑建立数据表外键

7年前 评论

碰到一个类似的情景,正好解惑了,感谢分享~~

6年前 评论

= = 也遇到这个问题了,感谢分享。

6年前 评论

我也遇到这个问题了 还是文档看的少啊 感谢分享

5年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!