Managing Cross-Table Sorting in Laravel Nova

Managing Cross-Table Sorting in Laravel Nova

Introduction

Laravel Nova, the elegantly designed administrative dashboard developed by Laravel itself, is known for its vast spectrum of features and its intuitive interface. From managing resources to customizing actions, Nova provides a sophisticated yet straightforward approach to data administration. However, as comprehensive as Laravel Nova may be, like any other technology, it doesn't always cover every nuanced need out of the box. One such challenge that developers often face is the implementation of cross-table sorting, which will be discussed in this article in detail.

Setting Up The Scene

To illustrate this workaround, let's consider a web application that allows users to connect their accounts. The database for this application has two tables: users and accounts, which are linked via the user_id foreign key on accounts:

To fill these tables with some test data, I've created two factories:

and implemented them via a seeder:

After running the seeder, in the Nova admin panel the users’ data will look like this:

Adding A Column That indicates The Number Of Connected Accounts

To start, we can add a column to the users table that indicates the number of connected accounts. This can be done by declaring an append property on the User model:

We can then update the User resource file to include the number_of_accounts field:

If we try to make that field sortable, it will throw an error saying that the column doesn’t exist, which is true as there’s no such column in users. A workaround to this is to override the indexQuery method and handle the sorting case by checking whether the orderBy and orderByDirection parameters are passed or not:

First we make sure to remove order clauses from the query, then manually join the accounts table and apply sorting in the SQL query.

Sorting By SUM/AVG

Using the same logic, we can write similar queries for the SUM/AVG of the values of the column balance and append these columns to users:

with the following translation to the builder language:

References