F
Filament9mo ago
bearer

Sort by related hasOno of Many model field Bug

Hey guys. I have some problem with relations. Tried to sort by field which is accessible via ->hasMany()->one()->ofMany()->some_field For example I have 2 models - Channel and ChannelPost A Channel has many ChannelPost. A ChannelPost have views field with count of views. Now in Channel model I have this relations:
/**
* @return HasMany
*/
public function posts(): HasMany
{
return $this->hasMany(ChannelPost::class);
}

/**
* @return HasOne
*/
public function lastPost(): HasOne
{
return $this->posts()->one()->ofMany('post_id', 'max');
}
/**
* @return HasMany
*/
public function posts(): HasMany
{
return $this->hasMany(ChannelPost::class);
}

/**
* @return HasOne
*/
public function lastPost(): HasOne
{
return $this->posts()->one()->ofMany('post_id', 'max');
}
In Filament table I use Tables\Columns\TextColumn::make('lastPost.views') When I tried to sort by this field - it was sorted randomly. So I tried to find the problem and did some debugging. Here we are receiving an empty model for Post - https://github.com/filamentphp/tables/blob/3.x/src/Columns/Concerns/InteractsWithTableQuery.php#L144 And then https://github.com/filamentphp/support/blob/3.x/src/Concerns/HasCellState.php#L172 - here we are getting query with channel_id = null (because empty model has id = null) And because this it generates looong SQL order by clause: with channel_posts.channel_id is null ```
GitHub
support/src/Concerns/HasCellState.php at 3.x · filamentphp/support
[READ ONLY] Subtree split of Filament's Support package (see filamentphp/filament) - filamentphp/support
GitHub
tables/src/Columns/Concerns/InteractsWithTableQuery.php at 3.x · fi...
[READ ONLY] Subtree split of the Filament Table Builder (see filamentphp/filament) - filamentphp/tables
2 Replies
CT
CT9mo ago
I had the same issue and I'm working on a PR for this, but it's kind of complicated as tbh I believe the core problem is actually in Laravel itself, so we're having to override some of the Eloquent behavior I did manage to get it working temporarily by overriding ->sortable() and doing a manual join, but there are two bugs with that I've discovered; 1. When sorting by a column and then selecting rows for bulk edit, the bulk editor is always passed all records (regardless of how many rows appear to be selected on the frontend). You only notice this when eg doing a dump or exporting say 3 rows but getting your entire table... 2. Filters aren't automatically applied when you override ->sortable() I think this one is easier to fix but I ran out of time and had to move onto other tasks. The core problem actually is because of a long-standing Laravel bug (which I would argue is a bug), in HasOneOrMany.php the following function:
public function addConstraints()
{
if (static::$constraints) {
$query = $this->getRelationQuery();

$query->where($this->foreignKey, '=', $this->getParentKey());

$query->whereNotNull($this->foreignKey);
}
}
public function addConstraints()
{
if (static::$constraints) {
$query = $this->getRelationQuery();

$query->where($this->foreignKey, '=', $this->getParentKey());

$query->whereNotNull($this->foreignKey);
}
}
specifically the line here; $query->where($this->foreignKey, '=', $this->getParentKey()); is the one that causes the problems, because our parent key is null it generates SQL that returns no rows.
bearer
bearerOP9mo ago
@ctoma Maybe you can publish you PR as WIP and I'll take a look and will try to help?
Want results from more Discord servers?
Add your server