Laravel 观察者和子/孙关系

发布于 2025-01-11 10:33:49 字数 1344 浏览 0 评论 0原文

我不确定我是否只是误解了 Laravel 中观察者的工作方式,或者我是否做错了什么。我目前在 Laravel 6 上运行,尽管该应用程序目前正在由另一个团队升级。

我所拥有的:

  • 父模型,称为 Parent
  • 父观察者,称为 ParentObserver
  • 子模型,称为 Child
  • 子观察者,称为 ChildObserver
  • 孙子模型,称为 Grandchild
class Parent extends Model
{
    public function children()
    {
        return $this->hasMany( Child::class );
    }
}
class Child extends Model
{
    public function grandchild()
    {
        return $this->hasOne( Grandchild::class );
    }
}

我的两个观察者都在服务提供者中声明,并且都被成功调用。我的问题,或者可能是误解,是关于观察者如何互动。

我的两个观察者都具有在收到删除命令时运行的功能。

class ParentObserver
{
    public function delete( Parent $parent )
    {
        $parent->children()->delete();
    }
}
class ChildObserver
{
    public function delete( Child $child )
    {
        $child->grandchild()->delete();
    }
}

ChildObserver 删除功能 100% 按预期工作。当我删除一个孩子时,孙子也会被删除。我感到困惑的是当我删除父级时。父级被删除,子级被删除,但孙级未被删除。我没有直接调用删除 ParentObserver 中的孙子,我期望 ChildObserver 功能将由 ParentObserver 中采取的操作触发。

我在设置观察者时错过了什么吗?或者,观察者中采取的操作是否不会触发其他观察者(如果它们位于代码的另一部分中,这些观察者通常会参与这些操作)?

I'm not sure if I'm just misunderstanding how Observers work in Laravel or if I'm doing something incorrectly. I'm currently running on Laravel 6, though this application is currently in the process of being upgraded by another team.

What I have:

  • Parent model, called Parent
  • Parent observer, called ParentObserver
  • Child model, called Child
  • Child observer, called ChildObserver
  • Grandchild model, called Grandchild
class Parent extends Model
{
    public function children()
    {
        return $this->hasMany( Child::class );
    }
}
class Child extends Model
{
    public function grandchild()
    {
        return $this->hasOne( Grandchild::class );
    }
}

Both of my observers are declared in a service provider, and both are called successfully. My question, or possibly misunderstanding, is about how observers interact.

Both of my observers have functionality that runs when a delete command is received.

class ParentObserver
{
    public function delete( Parent $parent )
    {
        $parent->children()->delete();
    }
}
class ChildObserver
{
    public function delete( Child $child )
    {
        $child->grandchild()->delete();
    }
}

The ChildObserver delete function works 100% as expected. When I delete a child, the grandchild also gets deleted. What I'm confused about is when I delete a Parent. The Parent is deleted, and the children are deleted, but the grandchildren are not. I am not directly calling to delete the grandchildren in ParentObserver, I was expecting that the ChildObserver functionality would get triggered by the actions taken in ParentObserver.

Did I miss something when setting up the observers? Or do actions taken in an observer not trigger other observers that would normally be engaged by those actions if they were in another part of the code?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

南城追梦 2025-01-18 10:33:49

这是进行批量删除查询。它不会为每个 Parent 的子级发出 deleted 事件。

class ParentObserver
{
    public function deleted( Parent $parent )
    {
        $parent->children()->delete();
    }
}

如果您更改为以下内容,它应该可以工作:

class ParentObserver
{
    public function deleted( Parent $parent )
    {
        $parent->children()->get()->each(function (Child $child) {
            $child->delete();
        });
    }
}

可能的改进:

  • cursor 方法是在 laravel 6 中实现的,因此您可以使用它而不是 get 来减少内存使用
  • 您可以使用高阶消息each 编写代码的方法更简单。
class ParentObserver
{
    public function deleted( Parent $parent )
    {
        $parent->children()->cursor()->each->delete();
    }
}

This is doing a mass delete query. It doesn't emit a deleted event for each of the Parent's children.

class ParentObserver
{
    public function deleted( Parent $parent )
    {
        $parent->children()->delete();
    }
}

It should work if you change to this:

class ParentObserver
{
    public function deleted( Parent $parent )
    {
        $parent->children()->get()->each(function (Child $child) {
            $child->delete();
        });
    }
}

Possible improvements:

  • The cursor method was implemented in laravel 6, so you could use it instead of get to reduce memory usage
  • You could use Higher Order Messages with the each method to make the code simpler.
class ParentObserver
{
    public function deleted( Parent $parent )
    {
        $parent->children()->cursor()->each->delete();
    }
}
雨巷深深 2025-01-18 10:33:49

来自 Laravel 的文档:

通过 Eloquent 发出批量更新或删除查询时,不会为受影响的模型调度已保存、更新、删除和删除的模型事件。这是因为在执行批量更新或删除时,永远不会实际检索模型。

因此,如果您正在进行批量删除或批量更新,它将不会触发。

From Laravel's documentation:

When issuing a mass update or delete query via Eloquent, the saved, updated, deleting, and deleted model events will not be dispatched for the affected models. This is because the models are never actually retrieved when performing mass updates or deletes.

So, if you are doing mass delete or mass update it won't trigger.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文