嗨,我正在努力尝试从多对多的关系中返回一条记录。
所以在我的应用程序中,我有俱乐部和地址实体。
分会有0,1或n个地址,其中一个可能是主要地址。
地址也可以被其他一些实体(如事件,成员等)使用。
我的表格如下:
clubs: id, name
addresses: id, street, city, zip club
club_address: id, club_id, address_id, is_main
我目前可以请求我俱乐部的所有地址:
class Club {
public function addresses()
{
return $this->belongsToMany('Address', 'club_address', 'club_id', 'address_id')->withPivot('is_main'); // club_address
}
}
现在我想要的是获得主要地址,或者在我申请俱乐部时为空。
我不能满足于简单地添加 - > wherePivot('is_main','=',1),因为当我想要一个数组或者null时它仍然返回一个1或0元素的数组。
我喜欢这样的东西
class Club {
// Get all the addresses in an array
public function addresses()
{
return $this->belongsToMany('Address', 'club_address', 'club_id', 'address_id')->withPivot('is_main'); // club_address
}
// Get the main address or null
public function address()
{
return $this->addresses()->wherePivot('is_main', '=', 1)->first();
}
}
但问题是我不能急于加载address
因为它没有返回一个关系模型......
答案 0 :(得分:0)
first()
返回一个集合 - 即使该集合为零(这是你基本上所说的)。
但是集合上的first()
返回null
是没有第一个......
所以..
class Club {
public function addresses()
{
return $this->belongsToMany('Address', 'club_address', 'club_id', 'address_id')->withPivot('is_main');
}
public function address()
{
// First first is on the model, second first
// is on the collection
return $this->addresses()
->wherePivot('is_main', '=', 1)
->first()
->first();
}
}
注意这实际上只是一个简写技巧。您的属性可以像以下一样轻松,可能更具可读性:
class Club {
public function addresses()
{
return $this->belongsToMany('Address', 'club_address', 'club_id', 'address_id')->withPivot('is_main');
}
public function address()
{
$record = $this->addresses()
->wherePivot('is_main', '=', 1)
->first();
return count($record) === 0 ? null : $record;
}
}
答案 1 :(得分:0)
我找到了一种方法来扩展BelongsToMany Relation类并使用它们的BelongsTo Relation等效覆盖两个方法。
但我不会说使用它是谨慎的,但对我的用途似乎没问题。
namespace App\Relations;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Query\Expression;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
class BelongsToOneFromMany extends BelongsToMany {
/**
* Initialize the relation on a set of models.
*
* @param array $models
* @param string $relation
* @return array
*/
public function initRelation(array $models, $relation)
{
foreach ($models as $model)
{
$model->setRelation($relation, null);
}
return $models;
}
/**
* Match the eagerly loaded results to their parents.
*
* @param array $models
* @param \Illuminate\Database\Eloquent\Collection $results
* @param string $relation
* @return array
*/
public function match(array $models, Collection $results, $relation)
{
$foreign = $this->foreignKey;
$other = $this->otherKey;
// First we will get to build a dictionary of the child models by their primary
// key of the relationship, then we can easily match the children back onto
// the parents using that dictionary and the primary key of the children.
$dictionary = array();
foreach ($results as $result)
{
$dictionary[$result->getAttribute($other)] = $result;
}
// Once we have the dictionary constructed, we can loop through all the parents
// and match back onto their children using these keys of the dictionary and
// the primary key of the children to map them onto the correct instances.
foreach ($models as $model)
{
if (isset($dictionary[$model->$foreign]))
{
$model->setRelation($relation, $dictionary[$model->$foreign]);
}
}
return $models;
}
}