将Eloquent透视值传递给Laravel API资源

um6iljoc  于 2023-02-14  发布在  其他
关注(0)|答案(2)|浏览(140)

Laravel 5.7.我有2口才模型:主人,猫
所有者型号:

public function cats()
{
    return $this->belongsToMany('App\Cat')->withPivot('borrowed');
}

猫型号:

public function owners()
{
    return $this->belongsToMany('App\Owner')->withPivot('borrowed');
}

cat_owner透视表具有以下字段:

id | cat_id | owner_id | borrowed
---------------------------------
1  |   3    |   2      |   1

我希望我的API返回所有猫的列表,如果登录用户借用了这只猫,我希望borrowed字段设置为true。
控制器:

public function index()
{
    return CatResource::collection(Cat::all());
}

目录资源:

public function toArray()
{
    $data = ['id' => $this->id, 'borrowed' => false];
    $owner = auth()->user();
    $ownerCat = $owner->cats()->where('cat_id', $this->id)->first();
    if ($ownerCat) {
        $data['borrowed'] = $ownerCat->pivot->borrowed == 1 ? true : false;
    }
    return $data;
}

这是可行的,但是为每只猫请求$owner似乎是浪费,例如,如果数据库中有5000只猫。有没有更有效的方法来做到这一点?我可以想到两种可能的方法:
1.将$owner传递给CatResource(需要重写现有集合资源)。
1.在传递给CatResource之前,首先在控制器中获取此信息。
我喜欢第二种方法,但不知道该怎么做。

eit6fx6z

eit6fx6z1#

尝试条件关系

public function toArray($request)
{
    return [
      'id' => $this->id,
      'borrowed' => false,
      'borrowed' => $this->whenPivotLoaded('cat_owner', function () {
         return $this->owner_id === auth()->id() && $this->pivot->borrowed == 1 ? true : false;
      })
   ];
}

然后调用return CatResource::collection(Cat::with('owners')->get());

4bbkushb

4bbkushb2#

你是对的,这会增加很多额外的负载。我认为你遇到了一个限制,那就是你不知道你想要哪个记录表单 cat_owner,直到你知道你正在使用的记录来自 catowner 表。
对于任何仍然感兴趣的人,我的解决方案是创建一个只提供透视值的资源
由于以下语句返回集合,因此您无法转到该集合上的透视表:

/*
* returns a collection
*/
$data['borrowed'] = $this->owners

/*
 * So this doesNOT work. Since you can’t get the pivot
 * data on a collection, only on a single record
 */
$data['borrowed'] = $this->owners->pivot

您应该接收集合,然后可以读取所有者记录的资源中的透视数据。如果此资源仅用于透视数据,我将其称为类似属性的东西。
为属性创建一个新资源,类似于:

class CatOwnerAttributeResource extends JsonResource
{
    public function toArray($request)
    {
      return [
          'borrowed' => $this->pivot->borrowed,
        ];
    }
}

然后像这样接收集合:

$data = ['id' => $this->id, 'borrowed' => false];

/*
 * Get the collection of attributes and grab the first (and only) record. 
 * NOTE: the filtering is done in the collection, not in the DBM. If there
 * is a possibility that the collection of owners who own this cat gets really 
 * big this is not the way to go! 
 */
if ($attributes =
  CatOwnerAttributeResource::collection(
    $this->owner
          ->where(‘id’ = $auth->user()->id)
          ->first() 
) {

  $data[‘borrowed’] = $attributes->borrowed == 1 ? true : false;
}
return $data;

无法运行此代码,所以请指出错误,如果你尝试它,它给你任何,我会调整。

相关问题