【问题标题】:How to get rock solid Eloquent relationships?如何获得坚如磐石的雄辩关系?
【发布时间】:2018-06-02 09:35:55
【问题描述】:

我一直在构建一个中型应用程序,现在正在启用许多辅助用例。这意味着更多地依赖事件和侦听器,并在单个请求中多次触摸对象。

在这个过程中,有几个案例让我对 Eloquent 关系的行为感到惊讶。显然,当我收到一个对象作为事件处理程序的参数时,我可能不知道它的详细历史记录,因此我需要了解何时/如何依赖它(以及何时/如何不依赖它)。

以我有一个父实体和许多子实体为例。这是父级的 Eloquent 关系:

public function children()
{
    return $this->hasMany(Model\Child::class);
}

在父级的其他地方,我有一种添加子级的方法,如下所示:

public function addChildren(array $data) 
{
    $children = [];

    foreach ($data as $child) {
      $children[] = new Child($child);
    }

    $this->children()->saveMany($children);
}

在请求周期的后期,我正在测试父级的一些条件,如果是真的,我让子级使用$parent->children,并与他们做一些进一步的工作。

在有人指出我错过了一条业务规则之前,这一直很好——如果父母已经有了孩子,你就不能以这种方式添加孩子。为了处理这个问题,我在addChildren()方法的顶部做了一个简单的测试:

public function addChildren(array $data)
{
    if(count($this->children)) { 
       throw new \Exception('Can not add children where they already exist');
    }

    // remainder of the method goes here...
}

当我添加此代码时,我开始得到意想不到的结果。经过调查,我发现通过在方法的早期计算孩子(显然意识到了这种关系),它会影响这种关系以后的表现。

我尝试在方法运行后转储$parent->children 的值。如果我排除首先计算孩子的代码,我会得到我所期望的 - 我新添加的孩子的集合。但是,如果我包含计数代码,我会得到一个空数组。

所以,问题是:

  • 我是否使用了错误的关系?
  • 我是不是对这种关系期望过高?
  • 如果我不知道当前请求上下文中对象的历史记录,是否应该始终取消设置并重新加载关系?
  • 我是否需要更深入地了解 Eloquent 才能对更复杂的用例充满信心?
  • 是否有一些简单的规则可以帮助我掌握它?
  • 还有什么...?

我非常喜欢 Laravel,所以很想了解这个亟待解决的问题......

编辑:

对于正在阅读这篇文章的任何人,我最终都会对用例的一些非核心部分进行排队。这对性能来说是一个很好的举措,并且在解耦方面感觉很好。因为 Laravel 序列化了 Eloquent 模型 id(而不是模型本身),它以一种相当优雅的方式给了我想要的效果。

【问题讨论】:

  • 您可以在检查过程中尝试刷新$this实例。 $this->fresh('children'),或者更好的是检查 $this->has('children')->get()$this->children()->exists() - 它对数据库执行查询。
  • fresh 返回一个新实例 ... load 加载关系 ... refresh 刷新当前实例

标签: laravel eloquent


【解决方案1】:

不,您没有以错误的方式使用关系,也没有期望过高。

有了 REST 的想法,大多数时候您不应该真正发现自己处于要加载关系、添加到它然后返回新关系的情况。如果你有一个 store 或 update 路由,那么你不需要预先加载关系(除非你有一个特定的用例),剩下的时间你应该只调用关系并返回结果。

如果出于某种原因,您需要修改关系(我相信有很多原因)然后返回结果,您总是可以重新加载关系,例如

$parent->fresh('children');

或者,如果您只想计算孩子的数量,您可以使用计数查询而不是获取所有 children

$parent->children()->count();

这不会加载关系,但会让您知道您有多少孩子。

【讨论】:

    猜你喜欢
    • 2013-04-07
    • 1970-01-01
    • 2020-12-02
    • 2021-01-16
    • 1970-01-01
    • 2020-10-18
    • 2017-10-12
    • 1970-01-01
    相关资源
    最近更新 更多