【问题标题】:hasManyThrough with an intermediate pivot tablehasManyThrough 与中间数据透视表
【发布时间】:2018-03-05 15:09:43
【问题描述】:

说明:

我的申请结构如下: PropertyManager 具有多对多关系,UnitProperty 具有一对多关系,即一个经理可以管理多个属性,一个属性可以有多个经理帐户,一个属性可以有多个单位。

我想与经理建立 HasManyThrough 关系以获取他的所有单位,因此理想情况下它看起来像:$manager->units,而不是通过每个属性循环并在其上调用 $property->units。当前版本的 laravel 可以做到这一点吗?

表格:

经理:

  • 身份证

属性:

  • 身份证

managers_properties:

  • manager_id
  • property_id

单位:

  • 身份证
  • property_id

【问题讨论】:

  • @GabMic 我已经查看了文档,但据我了解,我需要属性表上的 manager_id 列,这里不是这种情况
  • 那么恐怕 laravel 不会为您提供一种原生的“laravely”方式。 @毛里西奥

标签: laravel laravel-5 eloquent


【解决方案1】:

Eloquent 目前没有用于链式关系的方法,除了 hasManyThrough,它仅适用于 2 个链式 hasMany 关系。您应该创建自己的实现来获取相关资源。最简单的方法是在Manager 模型上定义一个accessor

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Support\Collection;

/**
 * @property-read Collection|\App\Models\Property[] $properties
 * @property-read Collection|\App\Models\Unit[] $units
 */
class Manager extends Model
{
    public function properties(): BelongsToMany
    {
        return $this->belongsToMany(Property::class);
    }

    public function getUnitsAttribute(): Collection
    {
        return $this->properties
            ->pluck('units')
            ->flatten(1)
            ->unique('id')
            ->sortBy('id');
    }
}

假设$manager instanceof App\Models\Manager,您现在应该可以使用$manager->units 访问相关单元。


注意

调用$manager->units 确实最多执行n + 1 数据库查询:1 用于获取n 相关属性,另一个n 用于获取每个返回属性的相关单元。 “最多”,因为资源可能已经加载,因为之前调用了访问器。

注意

调用$manager->units 会返回CollectionUnit 模型,这种格式等同于您从一对多关系方法的魔术访问器中获得的格式。但是getUnitsAttribute() 不是一个实际的关系方法(它不返回关系对象),因此不能这样处理,而Manager::properties() 可以。

【讨论】:

  • 有趣的解决方案,比我想象的要好。我可能会在他们的 github 上发布关于 hasManyThroughPivot 关系的提案,谢谢!
  • github.com/laravel/internals/issues/808如果你想加入讨论,感谢你
猜你喜欢
  • 2016-09-04
  • 2021-08-24
  • 2015-09-10
  • 2021-02-22
  • 2016-08-04
  • 1970-01-01
  • 2015-12-09
  • 2019-04-17
  • 1970-01-01
相关资源
最近更新 更多