Support the ongoing development of Laravel.io →
Database Eloquent

Hi there. Here is my problem

I have an eloquent model called Notification with a polymorphism relation called notifiable. I have two other models called Event and History which are notifiable, both of them "belongs_to" a User model. History also has a one to one relationship with an Item model.

I need to retrieve the 50 most recents notifications and i want to eager load notifiable object and all depending relations in order to create my view.

So far i've been able to eager load "notifiable', just by using ->with('notifiable') in the query builder.

Ex :

$notifications = Notification::orderBy('created_at')->limit(50)->with('notifiable');

But because the other relations are beyond the polymorphism one i can't name them in the with() call, things like 'notifiable.user' won' t load anything.

If i don't eager load i find myself with a ugly n+1 problem ( real case is 3 sql queries per notifications which is bad). I have managed to do that manually and i finally manage to obtain a very optimised query numbers. But i had to change things in my views. Basically the relations beyond the polymorphism one can't be called using

{{ $notification->notifiable->user->name }}

If you do so you are going to fire a sql query each time. Instead of that i had eager load datas in some arrays myself and get user's name by doing :

{{ $eventUsers[$notification->notifiable->id] }} 

or

{{ $historyUsers[$notification->notifiable->id] }} 

Is there a way to achieve this in a more Eloquent style ?

Philippe

ps: if something is unclear just ask a question and i will provide more informations.

Last updated 3 years ago.
0

You are saying that Event and History has a relationship with User, but you are trying to load the relationship on Notification?

Last updated 3 years ago.
0

Hi Herlevsen, i'm gonna try to explain a little bit deeper

Yes Event and History both 'belongs_to' User.

It starts with :

$notifications = Notification::orderBy('created_at')->limit(50)->with('notifiable');

in a controller. Then I call a view in which there is something like:

<ul>
@foreach($notifications as $notification)
    <li>
        @include('notifications._show'.get_class($notification->notifiable))
    </li>
@endforeach
</ul>

Meaning i have as many partials views as there are models 'notifiable' ( in my case _showEvent and _showHistory ) In a perfect world, inside, for example _showHistory partial i would have liked to write

{{ $notification->notifiable->user->name }} has an item named {{ $notification->notifiable->item->name }}

This actually works but you can't eager load it, it creates too many requests. So i had to eager load it myself, put things in array myself and i do things like :

{{ $userArray[$notification->notifiable->user_id]->name }} 
has an item named {{ $itemArray[$notification->notifiable->item_id]->name }}

That works okay but it's not very elegant, plus it makes reusability of my partials highly doubtable. But now it's hell faster .....

Hope this helps

Last updated 3 years ago.
0

Hi @elfif, have you found a clean solution for your problem ?

0

You can segregate each type of notification into their own collections and then eager load on the separate collections. I think that should eager load your original collection because of PHP's object by reference.

Try it out.

0

I'm curious as to the content of your notifiable() method on the Notification model and how you're able to even get a mixed collection in the first place. Can you post that?

0

Have you tried looking into using $with on the model?

protected $with = ['user'];

Just throwing out ideas.

0

Sign in to participate in this thread!

Eventy

Your banner here too?

elfif elfif Joined 7 Apr 2014

Moderators

We'd like to thank these amazing companies for supporting us

Your logo here?

Laravel.io

The Laravel portal for problem solving, knowledge sharing and community building.

© 2025 Laravel.io - All rights reserved.