Laravel 即使不询问属性,自定义属性也会加载关系

Laravel custom attributes loads relationships even when attribute is not asked

我有一个计算小队名称的自定义属性(让我们的前端团队生活更轻松)。

这需要加载一个关系,即使属性不是 called/asked(这种情况发生在 spatie query builder,模型上的一个 allowedAppends 数组被传递给查询构建器和带有所需附加项的 GET 参数)它仍然加载关系。

// Model
public function getSquadNameAttribute()
{
    $this->loadMissing('slots');
    // Note:  This model's slots is guaranteed to all have the same squad name (hence the first() on slots).
    $firstSlot = $this->slots->first()->loadMissing('shift.squad');
    return ($firstSlot) ? $firstSlot->shift->squad->name : null;
}

// Resource
public function toArray($request)
{
    return [
        'id'         => $this->id,
        'squad_name' => $this->when(array_key_exists('squad_name', $this->resource->toArray()), $this->squad_name),

        'slots'      => SlotResource::collection($this->whenLoaded('slots')),
    ];
}

注意:如果在上面的例子中没有被询问,squad_name 不会被返回,但是不管怎样

,关系仍在加载

我找到的一个可能的解决方案是编辑资源并包含 if's,但这会大大降低代码的可读性,我个人不是粉丝。

public function toArray($request)
{
    $collection = [
        'id'    => $this->id,

        'slots' => SlotResource::collection($this->whenLoaded('slots')),
    ];

    if (array_key_exists('squad_name', $this->resource->toArray())) {
        $collection['squad_name'] = $this->squad_name;
    }
    
    return $collection;
}

是否有另一种方法可以避免加载关系,如果在没有使用多个 if 向我的资源发送垃圾邮件的情况下不询问属性?

我发现的最简单和最可靠的方法是在助手 class 中创建一个函数来帮我检查。

这样您还可以根据需要自定义它。

-- RequestHelper class

public static function inAppends(string $value)
{
    $appends = strpos(request()->append, ',') !== false ? preg_split('/, ?/', request()->append) : [request()->append];
    return in_array($value, $appends);
}

-- 资源

'squad_name' => $this->when(RequestHelper::inAppends('squad_name'), function () {
    return $this->squad_name;
}),