F
Filament6mo ago
CT

How to add an ->orderBy() *after* all other orderBy's? Or modify query *after* query is built?

I have a resource with around 300 items in it. I am using ->defaultSort('created_at', 'desc') on the resource. It works well, but there is a bug. Because many of the items were added in chunks, say 15 a time, some have the same created_at date. The issue I have now is that when paginating with an offset, due to the non-guaranteed nature of MySQL I am getting some of the same items on page 2 as on page 1. I have verified this by running the queries directly against the database. The solution here would be to orderBy created_at and then id to ensure a consistent order. I know that ->defaultSort() accepts a closure and I could do this, but I will run into the same issue when the user sorts by any other columns that have many same values. I looked at ->modifyQueryUsing() but any orderBy is added before the default sort, or before the user sort, which ruins the sorting. Does anyone have a good solution? Thanks in advance.
1 Reply
CT
CTOP6mo ago
For anyone finding this in the future I came to the conclusion that there is no way to solve this in Filament, I could not find a way to hook into filament after the query is built, but before it is executed. So I solved it by extending the Eloquent Builder.
<?php

namespace App\Builders;

use Illuminate\Database\Eloquent\Builder;

class OrderedBuilder extends Builder
{
public function get($columns = ['*'])
{
$this->orderBy('id', 'asc');
return parent::get($columns);
}
}
<?php

namespace App\Builders;

use Illuminate\Database\Eloquent\Builder;

class OrderedBuilder extends Builder
{
public function get($columns = ['*'])
{
$this->orderBy('id', 'asc');
return parent::get($columns);
}
}
and in each specific Model that needs this behavior I added this;
public function newEloquentBuilder($query): OrderedBuilder
{
return new OrderedBuilder($query);
}
public function newEloquentBuilder($query): OrderedBuilder
{
return new OrderedBuilder($query);
}
I don't really like this solution but I could not find any better way to do it.
Want results from more Discord servers?
Add your server