Laravel hasManyThrough

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24994640/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 09:52:21  来源:igfitidea点击:

Laravel hasManyThrough

phplaraveleloquent

提问by Greg

I'm struggling to get my head around a hasManyThrough concept with laravel. I have three tables:

我正在努力理解 laravel 的 hasManyThrough 概念。我有三个表:

Bookings
    -id (int)
    -some other fields

Meta
    -id (int)
    -booking_id (int)
    -metatype_id (int)
    -some other fields

MetaType
    -id (int)
    -name (string)
    -some other fields

What I am trying to get is an Eloquent model that allows me to have a single booking record with multiple Meta records of type MetaType. I thought that hasManyThrough might have solved this, but now I am thinking that perhaps this is not the best way.

我想要得到的是一个 Eloquent 模型,它允许我拥有一个带有多个 MetaType 类型的 Meta 记录的单一预订记录。我认为 hasManyThrough 可能已经解决了这个问题,但现在我认为这可能不是最好的方法。

In my booking model I have

在我的预订模型中,我有

public function bookingmeta() {
    return $this->hasMany('bookingmeta','booking_id');
}

public function bookingmetatype() {
    return $this->hasManyThrough('bookingmetatype','bookingmeta','booking_id','bookingmetatype_id');
}

But this fails to generate the correct SQL and fails. I get

但这无法生成正确的 SQL 并失败。我得到

select `new_bookingmetatype`.*, `new_bookingmeta`.`booking_id` 
from `new_bookingmetatype` 
inner join `new_bookingmeta` 
on `new_bookingmeta`.`bookingmetatype_id` = `new_bookingmetatype`.`id` 
where `new_bookingmeta`.`booking_id` in (57103)

Whereas what I am really trying to achieve is

而我真正想要实现的是

select `new_bookingmetatype`.*, `new_bookingmeta`.`booking_id` 
from `new_bookingmetatype` 
inner join `new_bookingmeta` 
on `new_bookingmeta`.`id` = `new_bookingmetatype`.`bookingmetatype_id`  
where `new_bookingmeta`.`booking_id` in (57103)

If anyone can point me in the right direction I'd really appreciate it. Thanks.

如果有人能指出我正确的方向,我将不胜感激。谢谢。

回答by Jarek Tkaczyk

hasManyThroughis not the way at all. It works only for relations like this:

hasManyThrough根本不是办法。它只适用于这样的关系:

A hasMany/hasOne B, B hasMany/hasOne C, then A hasManyThrough C (through B)

What you have here is a many to many (belongsToMany), with metabeing the pivot table.

您在这里拥有的是多对多 ( belongsToMany),meta作为数据透视表。

So you can do this (assuming metais table name, Booking and MetaType are models):

所以你可以这样做(假设meta是表名,Booking 和 MetaType 是模型):

// Booking model
public function meta()
{
  return $this->belongsToMany('MetaType', 'meta', 'booking_id', 'metatype_id')
        ->withPivot([ ARRAY OF FIELDS YOU NEED FROM meta TABLE ]);
}

Then you can access all associated MetaType:

然后你可以访问所有关联的 MetaType:

$booking->meta; // collection of MetaType models

query it like this (eager loading):

像这样查询(急切加载):

$booking = Booking::with(['meta' => function ($q) {

  // query related table
  $q->where('someFieldOnMetaTypeTable', 'someValue')

    // and / or pivot table
    ->wherePivot('someFieldOnMetaTable', 'anotherValue');

}])->first();

or set constraints on the related table to filter the Booking:

或在相关表上设置约束以过滤预订:

$booking = Booking::whereHas('meta', function ($q) {

  // query related table
  $q->where('someFieldOnMetaTypeTable', 'someValue')

    // and / or pivot table
    ->where('meta.someFieldOnMetaTable', 'anotherValue');

})->first();

Note: wherePivotworks only when you eager load the relationship, so you can't use it in whereHasclosure.

注意:wherePivot仅当您急切加载关系时才有效,因此您不能在whereHas闭包中使用它。