Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

tomcodes's avatar

How to load a resource tool only on details page?

Hello,

I have made a resource tool that gives me more control on what can be displayed and done on a particular user.

I have added the resource tool in my nova resource:

public function fields(NovaRequest $request)
{
    return [
        ID::make()->sortable(),

        UserDetails::make($this)->onlyOnDetail()
    ];
}

Here is my resource tool that is quite SQL heavy:


class UserDetails extends ResourceTool
{
    public function __construct($model)
    {
        parent::__construct();

        $user = $model->resource;

        $this->withMeta([
            'user' => $user,
            'customerStatuts' => $user->getCustomerStatus(),
            'lastConnections' => Activity::where('log_name', 'login')->causedBy($user)->orderBy('id', 'desc')->take(10)->get(),
            'calendars' => $user->calendars,
            'offices' => $user->offices,
            'counters' => [
                'invoicesCount' => $user->invoices->count(),
                'events' => $user->events->count(),
                'upcomingEvents' => $user->events->where('start_at', '>', now())->count(),
                'upcomingEventsOnWaitingList' => $user->events->where('start_at', '>', now())->where('waiting_list', true)->count(),
            ],
            'acts' => $user->acts,
            'preferences' => $user->preference,
        ]);
    }
}

The thing is when I display a list of users, the resource tool is called for each line which leads to 450 SQL queries being executed.

How can I optimize this?

0 likes
1 reply
vincent15000's avatar

I see that you have many lines where you probably have a N+1 problem.

'customerStatuts' => $user->getCustomerStatus(), // call to a function for each resource
'lastConnections' => Activity::where('log_name', 'login')->causedBy($user)->orderBy('id', 'desc')->take(10)->get(), // call to a query for each resource
'calendars' => $user->calendars, // relationship ?
'offices' => $user->offices, // relationship ?
'invoicesCount' => $user->invoices->count(), // relationship ?
'events' => $user->events->count(), // relationship ?
'upcomingEvents' => $user->events->where('start_at', '>', now())->count(), // call to a query for each resource
'upcomingEventsOnWaitingList' => $user->events->where('start_at', '>', now())->where('waiting_list', true)->count(), // call to a query for each resource
'acts' => $user->acts, // relationship ?
'preferences' => $user->preference, // relationship ?

What I notice is that your are querying from inside the resource and also calling probably some relationships.

To avoid this problem, you need to eager load all relationships.

https://laravel.com/docs/10.x/eloquent-relationships#eager-loading

https://laravel.com/docs/10.x/eloquent-relationships#counting-related-models

About the queries, you should query another way from inside the controller and not separately for each resource in the resource.

Please or to participate in this conversation.