Eager loading media in Laravel when using Spatie's Media Library can be a bit tricky because the media are typically associated with a model using a polymorphic relationship. However, you can still optimize the query to reduce the number of database calls.
Here's a solution that should help you eager load the profile images and speed up the loading of your records:
- First, ensure that you have the
mediarelationship defined in yourUsermodel since the media is directly associated with it.
use Spatie\MediaLibrary\HasMedia;
use Spatie\MediaLibrary\InteractsWithMedia;
class User extends Model implements HasMedia
{
use InteractsWithMedia;
public function registerMediaCollections(): void
{
$this->addMediaCollection('profile');
}
}
- Next, in your
Personnelmodel, you can define a method to eager load the media for the associated user. This method will leverage theloadmethod on the collection to load the media for all related users at once.
class Personnel extends Model
{
// ... existing code ...
public function loadUserMedia()
{
$this->load(['user' => function ($query) {
$query->with('media');
}]);
}
}
- In your controller method, you can call this new method on the collection of
Personnelobjects after you retrieve them.
public function create(Training $training, Request $request)
{
// ... existing code ...
$members = Personnel::with(['rank', 'shift', 'station'])
->where('personnel.status', 1)
->orderBy('personnel.lastname', 'asc')
->orderBy('personnel.firstname', 'asc')
->get();
// Eager load the media for all related users
$members->each->loadUserMedia();
// ... existing code ...
return view('training.create', compact('methods', 'stations', 'units', 'shifts', 'skills', 'report', 'categories', 'location_type', 'default_startdt', 'default_enddt', 'training', 'members'));
}
- Finally, in your Blade template, you can access the media through the
userrelationship.
@foreach ($members as $key => $member)
@php
$user = $member->user; // Get the associated user
$hasProfileMedia = $user && $user->hasMedia('profile');
$profileMediaUrl = $hasProfileMedia ? $user->getFirstMediaUrl('profile', 'tiny') : null;
@endphp
<tr>
<!-- ... -->
<td class="m-0 p-0">
<img src="{{ $hasProfileMedia ? $profileMediaUrl : $defaultImageUrl }}"
alt="Default Image" name="member" id="member"
width="50px">
</td>
<!-- ... -->
</tr>
@endforeach
By using this approach, you're reducing the number of queries to the database by eager loading the media for all users in a single query, rather than having a separate query for each user's media. This should significantly improve the performance when loading a large number of records.