Little bit confused by table filters
I'm trying to setup a select dropdown filter, that when selected then needs to join onto another table and find relevant records.
If I use the baseQuery method, I can get the query to work, but it's applying, even when the filter isn't set to default. I have not been able to figure out another way to do it.
My select filter needs to query a column on a related record, not the main records in the table.
Solution:Jump to solution
```php
->query(function(EloquentBuilder $query, $state) {
$query->when(is_array($state) && !empty($state['values']), fn($query) =>
$query->whereHas('contributors', fn($query) =>
$query->select('contributors.id')...
62 Replies
Some additional info, this is my query code now:
->query(fn (EloquentBuilder $query, $state): EloquentBuilder => $query->join('contributors', 'contributors.article_id', 'articles.id')->where('contributors.user_id', $state))This complains about contributors being missing from the from clause, yet I'm applying the join. This is the resulting query (which is wrong):
select count(*) as aggregate from "articles" where ("contributors"."user_id" = ?)I haven't even selected an author yet, so I don't know why it's doing that... IT doens't appear to be applying the join, at all. I honestly have no idea.... I've tried 4 different approaches to get the query to behave as i need it to, stumped. Now it's not applying to the query at all... witaf is going on here.. This is my code: This is my hasAuthor scope: This is not being applied to the articles query, at all. Yet when I do a dd($authorId), it's showing the correctly selected value.
try wrapping your query modifier in a
if(!empty($state['value'])) { ... }
this should replace your
Yeah but it's not doing anything regardless. You would expect the default query conditions to be applied, even if there's no state value.
can i see the whole $table
make sure to utilize the relationship in displaying on a table ex
author.name
In your filter use SelectFilter::make('author_id')
@denknows it's from a related table though.
Below:
What's even trickier about this, is that authors, are found via a hasManyThrough relationship, which isn't supported by Filament, so I couldn't get the relationship working, either.
(as we have multiple authors on many of our articles)
Some people have had success with the has many deep plugin. https://github.com/staudenmeir/eloquent-has-many-deep
GitHub
GitHub - staudenmeir/eloquent-has-many-deep: Laravel Eloquent HasMa...
Laravel Eloquent HasManyThrough relationships with unlimited levels - GitHub - staudenmeir/eloquent-has-many-deep: Laravel Eloquent HasManyThrough relationships with unlimited levels
Never used it myself but might help.
Yeah I don't need that. It's a standard hasmanythrough relationship.
I"m either doing something seriously wrong, or select filters on tables were never meant for this use case, because I cannot get this to work, it's been days now.
I just don't understand why it's not applying the query. At all.
Okay, at a point where I think there's a big bug here.
My methods are being called (including my scopes), but nothing is being reflected in the actual queries.
Yeah filament is really getting in the way here. For some reason it's expecting a certain kind of relationship here - and that's just not going to work.
Dumb question, do you have a column for the author on table?
I do not - it's a related table, via has many through.
It's actually "authors"
It seems like the table isn’t eager loading the relationship and therefore the filter can’t run against it. I’m probably totally wrong, but it’s my immediate thought.
This area isn’t my strong point. Just trying to throw out possibilities.
It's a good theory - but, when I do it like this:
There are no errors - but the query is never applied. I can even dd() and see it calling the query parameters. It's doing some check elsewhere that's preventing the query being executed, which makes no sense to me.
tableFilters[author][value]=3 - in the query.
Have you tried doing it with an actual relationship for the select.? If it’s a has many then you’ll probably need to make it multiple so it can handle it. https://filamentphp.com/docs/3.x/tables/filters#relationship-select-filters
I’m also not understanding the $state[‘value’] part. Typically state is the value.
I have, the relationsihp on select won't accept hasManyThrough relationships.
Not for filters.
There's no need for multiple - I don't need to select multiple authors, I only want to search one at a time. There's a real strict setup for this selectfilter I'm finding.
Setting the options, and defining the query should be enough. But it's doing something else in the background that despite executing my query() method, it's not actually including it as part of the executed query for hte table.
I hear you, but multiple() is what allows the select to adjust its relationship query from belongsTo to HasMany.
Alrighty, I'll give it a go.
It could also be a limitation of select.js that is causing it to be that way too.
Okay, I got it workign with relationship using belongsToMany, but then the problem is how many results in returns due to the duplication.
HasManyThrough really should be able to work - the results are exactly the same as a hasMany lol
Hmmm, there's a new problem - it's only ever returning one article.
Hmm. It’s progress though. Lol.
I think this is a new brick wall if I'm being honest lol
I’m sure it works though. I just don’t have all the right steps to give you.
Wish I did.
NO worries, cheers dude
Yeah, another problem - it's not adding the table of the main model to the query for the id lookup in the filter, so I get an ambiguous id error 😮💨
Seems it's a known problem: https://github.com/filamentphp/filament/issues/8468 - another issue lost due to having to setup a repository.
GitHub
Filter by "hasManyThrough" not working · Issue #8468 · filamentphp/...
Package filament/filament Package Version v3.0.47 Laravel Version v10.22.0 Livewire Version No response PHP Version 8.2 Problem description This PR added the ability to search via "HasManyThro...
Yea. But we really need reproduction repos. It’s not feasible for use to set up relationships and seed them in the same way as seeing the error occur in your particular use case.
FS, I can't use the relationship for the select filter population as it doens't include authors that are yet to post...
Yeah, I know - my point previously however has been to just do the fix instead (most the stuff I've found has been pretty small)
PRs are always better than issues. 😁
I've figured it out. The select filter is making an assumption on data that exists in the database, which is not what I want here.
So now back at square 1 figuring out why my query isn't being applied.
If it doesn’t exist in the database then how can it filter, at least without a virtual column.
So two things on that - first thing is that having to query a many-many relationship for existing data, rather than the 50 or so author records I have, is considerably slower.
Secondly, it's okay if data doesn't exist, if you search for that author and they have nothing, no biggie.
What if you put your options() as a callback and use ->preload() on the select.
I tried doing that with the relationship, didn't do anything.
I can get everything to work, except the query being applied to the table query. And I have nfi why.
If I use baseQuery, I can see my query changes applied, but then it's querying the wrong column.
So you have a custom table query and custom filter queries on top of that.?
that's what I"m working through atm
Sounds like they might be competing with each other at the eloquent level. You might need some when’s to conditionally apply one or the other.
This is a guess obviously.
I need both, it seems - baseQuery to setup the join and condition, then query() to customise the where (ignore it)
I have a sneaking suspicion this is why I'm seeing developers use whereHas (imho, a really bad habit to fall into)
It exists for a reason, even if you don’t like it.😁
I'm not actually sure I understand the reason.
It's a far less performant approach to writing SQL queries for exists/counts.
And often you can use some SQL wizardry to be stupid fast
Maybe you’re experiencing the reason. Lol.
hahaha, I don't think it was designed for filament 😛
Filament is defaulting to laravels builder.
Not that I can’t guarantee it isn’t a bug.
Sigh, now looks like filament is adding a filler clause
ffs
Granted I haven’t had to do this kind of functionality but I have only have problems when my relationships weren’t actually setup correctly.
My relationships are fine, works everywhere else. The issue here is an opinionated select filter
Not saying yours aren’t correct.
I just can't understand why it's not applying my custom query clauses, despite executing them.
That’s what makes me the think there’s a conflict in the query. Can you dd the rawSql()
Either at the table query or the relationship query.
select * from "articles" where exists (select * from "contributors" where "articles"."id" = "contributors"."article_id" and 0 = 1)
that 0=1 is applying when I am not applying my query condition (as values aren't available)
PS. This step is the closest I've come. I can get it to filter now, but no filter = busted query
What is your base table query.?
Got it.
Solution
Lessons:
1. Applying query methods wherever you want won't work, shit is getting filtered -somewhere-.
2. Use baseQuery to do things like joins
3. Use query to do things like custom clauses
Now that I know this, I can go and clean this up so it's performant.
Thanks for trying to work through it with me, @awcodes
I ended up sorting it out. It was a combination of ignorance plus certainly some bugs on the Filament side - but I found a solution in the end.
Same problem?
if there a bugs, report them or they will not get solved i guess 🤷♂️
It takes far too long to setup a separate repository and get all the stuff working and setup to replicate, and you can't report bugs without it.
The approach is a mistake - some bugs are so simple that just replicating the code in a project showcases it. I get why it's there, but would be better to have a follow-up to ask for more info if it's required.
In my case, it does require a repo, as it's complicated.
if youve ever maintained open source youll know the frustration of attempting to replicate even the simplest of bugs and wasting time
when we are expected to do free work on behalf of the community, we want people to make an effort
Oh I get it, I do run a fairly good one - but my project is also much simpler, so I work with the authors to help replicate, or ask for more info.
I just think it would be better to accept the issues with a template, and if more info is really required, can ask for it. If none is forthcoming then can close it down after a period (via an automation)
yeah, well if you have a look at the number of issues we have then youll know that it would take a very long time to do that, and working asynchronously is much more efficient than waiting on authors to get their shit together
i honestly dont want the issue open if i cant immediately jump on it and action it when the time comes
No doubt, but at least you'd be aware of the issues. I've had 4 now, all 4 haven't been easy to step through.
anyway, someone will handle it when it is open with the required info
I'd rather pay, as I am - so i can stay focused on my outputs 🙂