using Version "spatie/laravel-medialibrary": "^6.0.0"
I am trying to fetch images of Listing Model and display it using foreach loop.
also used eager loading 'with' method with Listing Model.
So. How to avoid multiple database requests?
My Code is:
Controller File:
$listing = Listing::with('media')->findOrFail($listingId);
return view('dealer.inventory.inventory-other-details', compact('listing'));
View Blade File:
@foreach($listing->getMedia('damage_photos') as $image)
var file = {
name: '{{ $image->file_name }}',
size: '{{ $image->size }}',
url: '{{ $image->url }}'
};
myDropzone.options.addedfile.call(myDropzone, file);
myDropzone.options.thumbnail.call(myDropzone, file, file.url);
myDropzone.emit("complete", file);
myDropzone.files.push(file);
file.previewElement.id = file.name;
@endforeach
and also used @foreach($listing->media as $image)
All works, but it turns out a lot of queries to the database, please tell me how to avoid this
Thank you.
getMedia will perform it's own queries to lookup the right data.
If you perform YourModel::with('media') the media will have all media loaded. If you go that route, you should take care of filtering the $yourModel->media collection yourself.
I also tried with using $yourModel->media but same queries used.
no difference showed me.
why?
this issue is solved.
getUrl() method give me more query.
so, i replace getUrl() method to custompath(config('medialibrary.s3.domain').'/listing/'.$listingId.'/'.$media->file_name)
So, my code is:
$listing = Listing::with(['car', 'media'])->findOrFail($listingId);
foreach ($listing->media as $media) {
$url = config('medialibrary.s3.domain').'/listing/'.$listingId.'/'.$media->id.'/conversions/';
$media->url = $url.'375x375.jpg';
$media->compressed_url = $url.'compressed.jpg';
}
You may simply add a custom relationship method to your model that you can use to eager load all media collections or even a specific media collection.
// 'attachments' media collection
public function attachments()
{
return $this->media()->where('collection_name', 'attachments');
}
Now, to eager load, you have the following abilities:
\App\Listing::with('attachments')->get()$listing->load('attachments')You may simply add a custom relationship method to your model that you can use to eager load all media collections or even a specific media collection.
@kamalkhan This results in an N+1 problem... at least it did for me.
To properly eager load media models from a single Media Library Collection, you should do something like this:
use Illuminate\Database\Eloquent\Relations\MorphMany;
$listings = \App\Listing::with([
'media' => function (MorphMany $query) {
$query->where('collection_name', 'attachments');
}
])->get();
This will eager load all of your attachments for each model without eager loading other collections. This can be useful if you have lots of collections for a single model and those collections have a lot of records but you only want to return Media for a specific collection.
I have 4 Models (\App\Resource) and each Model contains 2 single media collections: thumbnail and preview.
Let's take a look at 2 queries...
QUERY 1
$resources = Resource::with(['media'])->get();
This query results in:
QUERY 2
use Illuminate\Database\Eloquent\Relations\MorphMany;
$resources = Resource::with([
'media' => function (MorphMany $query) {
$query->where('collection_name', 'thumbnail');
}
])->get();
This query results in:
The 2nd query reduces the number of hydrated Media models by half. Reducing the number of hydrated models reduces the amount of memory usage of your page.
Hope this helps!
@EricBusch I don't think that's entirely true.
Your first query is collecting both the thumbnail and the preview media collections which results in 8 hydrations (4 thumbnail and 4 preview collections)
Whereas, your second query is only accessing the thumbnail collection, hence only 4 hydrations (only 4 thumbnail collections).
But as far as collecting both the collections, your second query will have 2 queries as opposed to your first query which i think will have 4 queries. But still, your first query isn't using the relationship I suggested.
Most helpful comment
getMediawill perform it's own queries to lookup the right data.If you perform
YourModel::with('media')the media will have all media loaded. If you go that route, you should take care of filtering the$yourModel->mediacollection yourself.