Tricks

Use sortable() on columns pointing to one-to-many relationship

Oct 21, 2022
studiowizjo
Admin panel, Table builder

Want to use sortable() on column which points one-to-many relationship, but got following error?

SQLSTATE[21000]: Cardinality violation: 1242 Subquery returns more than 1 row

You can do it as follows:

use Illuminate\Database\Eloquent\Builder;
 
TextColumn::make('positions.name')
->sortable(query: function (Builder $query, string $direction, $column): Builder {
[$table, $field] = explode('.', $column->getName());
 
return $query->withAggregate($table, $field)
->orderBy(implode('_', [$table, $field]), $direction);
})

It works for both hasMany and morphToMany relationships.

If you plan to use it throughout your application, you may want to add a macro in your sevice provider:

Column::macro('sortableMany', function () {
return $this->sortable(query: function (Builder $query, string $direction, $column): Builder {
[$table, $field] = explode('.', $column->getName());
 
return $query->withAggregate($table, $field)
->orderBy(implode('_', [$table, $field]), $direction);
});
});

and use on column your new method:

TextColumn::make('positions.name')
->sortableMany()

No comments yet…