【问题标题】:Query multiple table relationships using Laravel Eloquent Models使用 Laravel Eloquent 模型查询多个表关系
【发布时间】:2021-08-27 23:30:00
【问题描述】:

我正在尝试使用 一对一一对多多对的 Laravel Eloquent 模型查询多个表许多关系。

我有一个forms 表、一个brands 表、一个users 表和一个brand_groups pivot 表。

每个表单都有一个品牌和一个用户:

forms
  ID
  user_id
  brand_id

品牌没有任何外键:

brands
  ID

用户没有任何外键:

users
  ID

还有一个数据透视表可以创建多对多关系,用于创建拥有许多用户(如品牌成员)的品牌组:

brand_groups
  brand_id
  user_id

我正在尝试通过直接所有权 (forms.user_id) 或品牌会员资格获取属于用户的所有表单,该用户通过 brand_groups many 成为会员的所有品牌的所有表单到许多数据透视表。

例如,我们有 2 个品牌,2 个用户,1 个用户是 1 个品牌的成员:

brand(ID: 1)
brand(ID: 2)

user(ID: 1)
user(ID: 2)

brand_group(brand_id: 1, user_id: 1)

form(ID: 1, user_id: 1,    brand_id: null)
form(ID: 2, user_id: null, brand_id: 1)
form(ID: 3, user_id: 2,    brand_id: 1)
form(ID: 4, user_id: 1,    brand_id: 2)

使用 Laravel Eloquent 模型不是直接的 DB 外观调用),我想检索属于用户的所有表单。 user(ID:1) 有 3 种形式:

form(ID:1) 直接用户所有权
form(ID:2) 用户是brand(ID:1) 组的成员,这是form(ID:2) 的品牌
form(ID:3) 用户是brand(ID:1) 组的成员,这是form(ID:3)的品牌

我用Eloquent: Relationships - Has Many Through试了一下:

Has Many Through

“has-many-through”关系提供了一种通过中间关系访问远距离关系的便捷方式。

我试过这样:

class User extends Model
{
    public function forms()
    {
        return Forms::hasManyThrough(
            Form::class,
            BrandGroups::class,
            'brand_id',
            'brand_id',
            'id',
            'form_id',
        )->where('id', $this->id);
    }
}

但我收到如下错误:

BadMethodCallException with message 'Call to undefined method App\Models\Form::brand_groups()'

编辑

经过一番挖掘,我设法想出了可以为用户返回所有表单的工作 MySQL 代码:

SELECT * FROM `forms`
WHERE EXISTS (
  SELECT `brand_id`, `user_id`
  FROM `brand_groups`
  WHERE `forms`.`brand_id` = `brand_groups`.`brand_id`
    AND `brand_groups`.`user_id` = 1
) OR `forms`.`user_id` = 1

现在我只需将该查询转换为一个雄辩的模型关系。

雄辩的模型

User.php

class User extends Authenticatable implements MustVerifyEmail
{
    public function brands()
    {
        return $this
            ->belongsToMany(Brand::class, 'brand_groups')
            ->using(BrandGroups::class)
            ->as('member');
    }

    public function forms()
    {
        return $this->hasMany(Form::class, 'user_id');
    }
}

Brand.php

class Brand extends Model
{
    protected $table = 'brands';

    public function forms()
    {
        return $this->hasMany(Form::class);
    }

    public function members()
    {
        return $this
            ->belongsToMany(User::class, 'brand_groups')
            ->using(BrandGroups::class)
            ->as('member');
    }
}

Form.php

class Form extends Model
{
    protected $table = 'forms';

    public function owner()
    {
        return $this->belongsTo(User::class);
    }

    public function brand()
    {
        return $this->belongsTo(Brand::class);
    }
}

更新

我设法找到一个查询来获取与这样的用户相关的所有表单:

class User extends Authenticatable implements MustVerifyEmail
{
    ...

    public function allForms()
    {
        return Form::where(function ($q) {
            $q->whereExists(function ($q) {
                $q->from('brand_groups')
                    ->where('forms.brand_id', DB::raw('brand_groups.brand_id'))
                    ->where('brand_groups.user_id', $this->id);
            })->orWhere('owner_id', $this->id);
        });
    }
}

如何将其转换为直接的User 模型雄辩关系?

【问题讨论】:

    标签: mysql laravel eloquent eloquent-relationship


    【解决方案1】:

    您是否尝试过Eager Load 用户模型关系?

    编辑 首先:数据透视表名称应该是两个表的单数-snake_case-名称,并且应该按字母顺序排列(brand_user)

    接下来,尝试以下操作:

    return User::where(‘id’, $this->id)->with([‘forms’,‘brands.forms’)->get();
    

    这应该返回具有直接所有权的表单以及用户品牌及其关联的表单

    【讨论】:

    • ERROR Illuminate\Database\Eloquent\RelationNotFoundException with message 'Call to undefined relationship [brand_groups] on model [App\Models\Form].' forms 表和brand_groups 表没有直接关系; brand_groups 表是连接usersbrands 的数据透视表。
    • 你能发布你的模型吗?
    • 我已经用雄辩的模型及其关系更新了我的问题。
    • 我编辑了我的答案,试着保持更新。
    • 感谢您花时间研究这个问题。无需任何修改,您编辑的 eloquent 查询就可以工作,但它不会将表单分组到一个集合中,所以我得到了用户是具有 <query>->forms 的所有者的所有表单,然后我得到了所有品牌的集合用户属于使用<query>->brands<each>->forms,这是一个很好的步骤(对此表示赞成),但我想有一个查询,我可以得到一个集合中的所有表单。我知道这是可能的;你知道我将如何实现查询以获取单个集合中的所有表单吗?
    猜你喜欢
    • 2014-10-31
    • 2017-11-03
    • 2021-09-25
    • 2018-03-01
    • 2018-10-20
    • 1970-01-01
    • 2016-12-01
    • 2019-11-03
    • 2013-10-03
    相关资源
    最近更新 更多