2016-11-04 70 views
1

我有两个模型,UserSeminar。在英语中,基本思想是一群用户参加任何数量的研讨会。此外,每个研讨会上只有一名用户可以自愿发言。Laravel - Flatten data via`with`

我的实现由users表,seminars表和seminar_user数据透视表组成。

seminar_user表有这样的结构:

seminar_id | user_id | speaking 
-------------|-----------|--------- 
    int  | int | bool 

的关系定义如下:

/** On the Seminar model */ 
public function members() 
{ 
    return $this->belongsToMany(User::class); 
} 

/** On the User model */ 
public function seminars() 
{ 
    return $this->belongsToMany(Seminar::class); 
} 

我竭力要弄清楚如何设置当中,将会以“关系”帮助我获得研讨会的演讲者。我目前已经定义的方法是这样的:

public function speaker() 
{ 
    return $this->members()->where('speaking', true); 
} 

我想其原因,这是因为最终,我想我的API调用看起来像这样:

public function index() 
{ 
    return Seminar::active() 
     ->with(['speaker' => function ($query) { 
      $query->select('name'); 
     }]) 
     ->get() 
     ->toJson(); 
} 

的问题是由于members关系实际上是一个belongsToMany,即使我知道只有一个User其中speaking为真,一个User的数组将始终返回。

一个解决办法是后格式化发送它,首先设置一个临时$seminars变量,然后通过foreach去和设置每个$seminar['speaker'] = $seminar['speaker'][0]前的响应,但真的很臭,我觉得应该有办法通过雄辩本身实现这一点。

如何将通过with调用添加的数据变平? (或重写我的关系方法)

回答

1

试着改变你的speaker功能,这

public function speaker() 
{ 
    return $this->members()->where('speaking', true)->first(); 
} 

这将永远给你一个项目,而不是你目前收到的集合。

+1

这会不会让你玩与查询,并且不会让您使用'with'作为模型中的关系热切加载它。 –

+0

@JosephSilber可能会......但这会解决OP的问题。 – linuxartisan

+0

谢谢@JosephSilber ...这正是我没有采用这种方法的原因。 – tam5

0

您可以在Seminar模型定义了一个新的关系:

public function speaker() 
{ 
    return $this->belongsToMany(User::class)->wherePivot('speaking', true); 
} 

和您的查询就会为:

Seminar::active() 
    ->with(['speaker' => function ($query) { 
     $query->select('name'); 
    }]) 
    ->get() 
    ->toJson(); 

Docs向下滚动到Filtering Relationships Via Intermediate Table Columns

+0

实际上,这段代码和我目前所拥有的唯一区别就是你已经把'where'改成'wherePivot'。在这种情况下,它会返回完全相同的结果,因此您的解决方案会得到与我已有的结果相同的结果。:( – tam5

+0

区别也是'$ this-> belongsToMany()'。你试过吗? –

+0

实际上,我调用'members'函数返回相同的'belongsToMany',这就是为什么我说它是不管怎样,是的,我已经尝试过了,问题是'belongsToMany'假定多个值可能被取回,所以它返回一个对象数组,即使只有一个值存在。 – tam5