Sep 8, 2025
1
Level 2
Model Accessors ignore mergeWhen condition and executes
Hi there,
I have this UserResource for my REST API:
/**
* @mixin \App\Models\User
*/
class UserResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'type' => 'user',
'attributes' => [
'name' => $this->name,
'email' => $this->email,
$this->mergeWhen($this->relationLoaded('latestSubscription'), [
'subscriptionStatus' => $this->subscription_status,
]),
This is how the attribute is defined:
/**
* Get the user's subscription status.
*/
protected function subscriptionStatus(): Attribute
{
\Log::debug('subscription_status is called');
return Attribute::make(
function () {
if ($this->hasPermissionTo(Permissions::GOLDEN_PASS)) {
return SubscriptionStatusEnum::GOLDEN_PASS->value;
}
if (! $this->relationLoaded('latestSubscription')) {
return null;
}
return $this->latestSubscription->status ?? SubscriptionStatusEnum::PROSPECT->value;
}
);
}
Problem: subscription_status attribute is fired, and the queries inside are made (hasPermissionTo) even though the relationship is not loaded, and i get "subscription_status is called" in my logs. I thought mergeWhen will not execute the callback unless the first condition is false, and it is false (given that "subscriptionStatus" is never returned in the response.
Am I misunderstanding what mergeWhen does, and is there an alternative that does what I want?
Thanks
Please or to participate in this conversation.