首页 > 解决方案 > 即使不询问属性,Laravel 自定义属性也会加载关系

问题描述

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

这需要加载一个关系,即使该属性没有被调用/询问(这发生在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 ,但这严重降低了代码的可读性,我个人不是粉丝。

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 向我的资源发送垃圾邮件的情况下不询问属性,是否有另一种方法可以避免加载关系?

标签: laravellaravel-resource

解决方案


我发现的最简单和最可靠的方法是在帮助程序类中创建一个函数来为我检查这个。

这样,您还可以根据需要对其进行自定义。

-- RequestHelper 类

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;
}),

推荐阅读