2

I have a custom attribute that calculates the squad name (to make our frontend team lives easier).

This requires a relation to be loaded and even if the attribute is not being called/asked (this happens with spatie query builder, an allowedAppends array on the model being passed to the query builder and a GET param with the required append(s)) it still loads the relationship.

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

Note: squad_name does not get returned if it's not being asked in the above example, the relationship is however still being loaded regardless

A possible solution I found was to edit the resource and includes if's but this heavily reduces the readability of the code and I'm personally not a fan.

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

Is there another way to avoid the relationship being loaded if the attribute is not asked without having spam my resource with multiple if's?

1 Answer 1

0

The easiest and most reliable way I have found was to make a function in a helper class that checks this for me.

This way you can also customize it to your needs.

-- RequestHelper class

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

-- Resource

'squad_name' => $this->when(RequestHelper::inAppends('squad_name'), function () {
    return $this->squad_name;
}),
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.