2

I am playing for the first time with API Resource in laravel 12.

I have this situation:

The product has many Skus:

public function skus(): HasMany
{
   return $this->hasMany(Sku::class);
}

The skus has many images:

public function images(): HasMany
{
   return $this->hasMany(SkuImage::class)->orderBy('sort');
}

So from the product controller I use:

Product::with(['skus.images'])....

to receive the skus and the images.

In ProductResource:

...
'skus' => $this->whenLoaded('skus', function () {
    return $this->skus->map(function ($sku) {
        return [
           'id' => $sku->id,
           ...
           // the problem is here -> Call to undefined method App\\Models\\Sku::whenLoaded()
           'images' => $sku->whenLoaded('images', function ($sku) {
               return $sku->images->map(function ($image) {
                   return [
                       'id' => $image->id,
                       'filename' => $image->filename,
                       'size' => $image->size,
                   ];
               });
           }),
        ];
    });
}),
...

I want to load the images only when the images relation is loaded from skus with(['skus.images']), else show only the sku data with(['skus']) when not loading the images.

How can I do that?

4
  • did you install the spatie/query-builder package? i guess this method is of that package Commented Jun 27 at 10:36
  • @sandipbharadva no Commented Jun 27 at 10:41
  • look into the package salamwaddah/laravel-relation-parser it allows you to conditionally load relations based on the request. Commented Jul 1 at 12:37
  • @calin24 you need to install that package Commented Jul 2 at 7:00

1 Answer 1

0

As error suggest whenLoaded is undefined method. whenLoaded only works on models on which resource is called on.

Solution 1

You can use relationLoaded for images.

use Illuminate\Http\Resources\MissingValue;

...
'skus' => $this->whenLoaded('skus', function () {
    return $this->skus->map(function ($sku) {
        return [
            'id' => $sku->id,
            'images' => $sku->relationLoaded('images') ?
                $sku->images->map(function ($image) {
                    return [
                        'id' => $image->id,
                        'filename' => $image->filename,
                        'size' => $image->size,
                    ];
                }) : app(MissingValue::class),
        ];
    });
}),
...

Solution 2

You can define resources for model separately.

In ProductResource:

'skus' => $this->whenLoaded('skus', $this->skus->toResource()),

In SkuResource:

'id' => $this->id,
'images' => $this->whenLoaded('images', $this->images->toResource()),

In ImageResource:

'id' => $this->id,
'filename' => $this->filename,
'size' => $this->size,
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.