Quantcast

Filters on get_posts()

classic Classic list List threaded Threaded
12 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Filters on get_posts()

John Blackbourn
These days I find myself using multiple additional loops on the
majority of sites I build, as I'm sure many people on this list do.
The problem I'm now running into is the all-or-nothing filtering on
the get_posts() function which is used for additional loops.

By default, get_posts() sets the 'suppress_filters' parameter to
'true' meaning all the filters such as 'posts_where', 'posts_join' and
'posts_request' are not applied. This is desired behaviour, because
plugins that use these filters often filter the query based on the
global conditionals and the main WordPress query. If these filters
were applied to additional loops then we'd probably get unexpected
results.

So the problem is that with 'suppress_filters' set to 'true', we're
left with absolutely no filters on get_posts(). (Well, we have the
'posts_search' filter that affects the query if we're doing a search,
but that's it.)

I'd like to use get_posts() to get posts for my additional loop, but
I'd also like to filter the query string so I can join an additional
table (specifically, the translations lookup table from WPML [1] in
order to fetch translated posts). The only filter I can use is the
all-encompassing 'query' filter which applied to every single database
query.

In order to get around this I'm currently adding a filter to 'query'
before calling get_posts() and removing the filter immediately
afterwards. This is not good for my OCD. I also contemplated fetching
the posts and then fetching the translated posts in a second query,
but this isn't ideal either (especially as WPML is a bit heavy on
queries anyway).

Is there an argument here for adding a filter to the get_posts() query
string that's applied regardless of the 'suppress_filters' argument?
Is that just asking for trouble from plugins that end up incorrectly
using this filter? Or is there a better way of going about this?

Regards,
John

P.S. I'm aware of the 'pre_get_posts' action that affects the query
object in this function, but this only lets you control the query
arguments used to build the query string, not the query string itself.

[1] http://wpml.org/
_______________________________________________
wp-hackers mailing list
[hidden email]
http://lists.automattic.com/mailman/listinfo/wp-hackers
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Filters on get_posts()

Mike Schinkel-5
John,

I have run into pretty much the same issues.  That's why I wrote this ticket:

http://core.trac.wordpress.org/ticket/15063

The solution proposed in ticket may or may not be good but the problem it was trying to address is real.  

-Mike

On Oct 11, 2010, at 12:14 AM, John Blackbourn wrote:

> These days I find myself using multiple additional loops on the
> majority of sites I build, as I'm sure many people on this list do.
> The problem I'm now running into is the all-or-nothing filtering on
> the get_posts() function which is used for additional loops.
>
> By default, get_posts() sets the 'suppress_filters' parameter to
> 'true' meaning all the filters such as 'posts_where', 'posts_join' and
> 'posts_request' are not applied. This is desired behaviour, because
> plugins that use these filters often filter the query based on the
> global conditionals and the main WordPress query. If these filters
> were applied to additional loops then we'd probably get unexpected
> results.
>
> So the problem is that with 'suppress_filters' set to 'true', we're
> left with absolutely no filters on get_posts(). (Well, we have the
> 'posts_search' filter that affects the query if we're doing a search,
> but that's it.)
>
> I'd like to use get_posts() to get posts for my additional loop, but
> I'd also like to filter the query string so I can join an additional
> table (specifically, the translations lookup table from WPML [1] in
> order to fetch translated posts). The only filter I can use is the
> all-encompassing 'query' filter which applied to every single database
> query.
>
> In order to get around this I'm currently adding a filter to 'query'
> before calling get_posts() and removing the filter immediately
> afterwards. This is not good for my OCD. I also contemplated fetching
> the posts and then fetching the translated posts in a second query,
> but this isn't ideal either (especially as WPML is a bit heavy on
> queries anyway).
>
> Is there an argument here for adding a filter to the get_posts() query
> string that's applied regardless of the 'suppress_filters' argument?
> Is that just asking for trouble from plugins that end up incorrectly
> using this filter? Or is there a better way of going about this?
>
> Regards,
> John
>
> P.S. I'm aware of the 'pre_get_posts' action that affects the query
> object in this function, but this only lets you control the query
> arguments used to build the query string, not the query string itself.
>
> [1] http://wpml.org/
> _______________________________________________
> wp-hackers mailing list
> [hidden email]
> http://lists.automattic.com/mailman/listinfo/wp-hackers

_______________________________________________
wp-hackers mailing list
[hidden email]
http://lists.automattic.com/mailman/listinfo/wp-hackers
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Filters on get_posts()

scribu-2
In reply to this post by John Blackbourn
On Mon, Oct 11, 2010 at 7:14 AM, John Blackbourn
<[hidden email]<johnbillion%[hidden email]>
> wrote:

> I'd like to use get_posts() to get posts for my additional loop, but
> I'd also like to filter the query string so I can join an additional
> table (specifically, the translations lookup table from WPML [1] in
> order to fetch translated posts). The only filter I can use is the
> all-encompassing 'query' filter which applied to every single database
> query.
>

You can just pass suppress_filters => false to get_posts().
_______________________________________________
wp-hackers mailing list
[hidden email]
http://lists.automattic.com/mailman/listinfo/wp-hackers
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Filters on get_posts()

Casey Bisson-2
In reply to this post by John Blackbourn

John,

I think your approach here is good. That is, there's no reason a filter has to be blindly activated as WP is instantiated, and the globally applied.

Filters such as you describe should look at the context of the query and optionally activate themselves. Then immediately deactivate once their work is done. The parse-query and pre-get-posts actions are good places to apply filters, then simply remove_filter() as you run them.

If you're running multiple loops, you can do yourself a favor by calling do_action('my_loop_name') just before calling wp_query(), as that will give you an opportunity to set whatever filters you want based on that specific loop/query.

--Casey

http://MaisonBisson.com

On Oct 10, 2010, at 9:14 PM, John Blackbourn <[hidden email]> wrote:

> In order to get around this I'm currently adding a filter to 'query'
> before calling get_posts() and removing the filter immediately
> afterwards. This is not good for my OCD. I also contemplated fetching
> the posts and then fetching the translated posts in a second query,
> but this isn't ideal either (especially as WPML is a bit heavy on
> queries anyway).
_______________________________________________
wp-hackers mailing list
[hidden email]
http://lists.automattic.com/mailman/listinfo/wp-hackers
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Filters on get_posts()

John Blackbourn
In reply to this post by scribu-2
On Mon, Oct 11, 2010 at 10:45 AM, scribu <[hidden email]> wrote:
>
> You can just pass suppress_filters => false to get_posts().

As I stated this can lead to side effects because many plugins add
filters to 'posts_where' etc and use global conditionals (which are
irrelevant to my additional loop) to determine how to filter the
query. An example might be a plugin that filters 'posts_where' and
adds an additional clause when is_home() evaluates to true. I don't
want this clause showing up in my additional loop.
_______________________________________________
wp-hackers mailing list
[hidden email]
http://lists.automattic.com/mailman/listinfo/wp-hackers
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Filters on get_posts()

John Blackbourn
In reply to this post by Casey Bisson-2
On Mon, Oct 11, 2010 at 1:02 PM, Casey Bisson <[hidden email]> wrote:
>
> John,
>
> I think your approach here is good. That is, there's no reason a filter has to be blindly activated as WP is instantiated, and the globally applied.

I've never thought about it that way actually. I always thought of
subsequently removing filters at runtime as being a bit hacky, but
you're right.

> Filters such as you describe should look at the context of the query and optionally activate themselves. Then immediately deactivate once their work is done. The parse-query and pre-get-posts actions are good places to apply filters, then simply remove_filter() as you run them.
>
> If you're running multiple loops, you can do yourself a favor by calling do_action('my_loop_name') just before calling wp_query(), as that will give you an opportunity to set whatever filters you want based on that specific loop/query.
>
> --Casey

I'll try this approach and see how I get on. Cheers.
_______________________________________________
wp-hackers mailing list
[hidden email]
http://lists.automattic.com/mailman/listinfo/wp-hackers
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Filters on get_posts()

John Blackbourn
In reply to this post by Mike Schinkel-5
On Mon, Oct 11, 2010 at 6:30 AM, Mike Schinkel
<[hidden email]> wrote:
> John,
>
> I have run into pretty much the same issues.  That's why I wrote this ticket:
>
> http://core.trac.wordpress.org/ticket/15063
>
> The solution proposed in ticket may or may not be good but the problem it was trying to address is real.
>
> -Mike

The natural extension to that is to add context to hooks and filters
too. I believe this has been discussed before, and is long overdue
IMO.
_______________________________________________
wp-hackers mailing list
[hidden email]
http://lists.automattic.com/mailman/listinfo/wp-hackers
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Filters on get_posts()

scribu-2
In reply to this post by John Blackbourn
On Mon, Oct 11, 2010 at 5:27 PM, John Blackbourn
<[hidden email]<johnbillion%[hidden email]>
> wrote:

> On Mon, Oct 11, 2010 at 10:45 AM, scribu <[hidden email]> wrote:
> >
> > You can just pass suppress_filters => false to get_posts().
>
> As I stated this can lead to side effects because many plugins add
> filters to 'posts_where' etc and use global conditionals (which are
> irrelevant to my additional loop) to determine how to filter the
> query. An example might be a plugin that filters 'posts_where' and
> adds an additional clause when is_home() evaluates to true. I don't
> want this clause showing up in my additional loop.
>

Context is already provided: the wp_query object itself. This was only
introduced in WP 2.9 so most plugins still have to catch up.

get_posts() also sets 'caller_get_posts' => true, so plugins can use that.
In WP 3.1 'caller_get_posts' was then renamed to 'ignore_stickies':

http://core.trac.wordpress.org/ticket/14624

We should probably un-deprecate 'caller_get_posts'.
_______________________________________________
wp-hackers mailing list
[hidden email]
http://lists.automattic.com/mailman/listinfo/wp-hackers
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Filters on get_posts()

Mike Schinkel-5
In reply to this post by John Blackbourn
On Oct 11, 2010, at 10:33 AM, John Blackbourn wrote:
> The natural extension to that is to add context to hooks and filters
> too. I believe this has been discussed before, and is long overdue

+1.   Adding context into the system would be hugely beneficial for managing the complexities that Custom Post Types have made possible.

-Mike
_______________________________________________
wp-hackers mailing list
[hidden email]
http://lists.automattic.com/mailman/listinfo/wp-hackers
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Filters on get_posts()

Mike Schinkel-5
In reply to this post by scribu-2
On Oct 11, 2010, at 10:50 AM, scribu wrote:
> Context is already provided: the wp_query object itself. This was only
> introduced in WP 2.9 so most plugins still have to catch up.

Not enough.  

A binary property like 'caller_get_posts'  cannot capture the infinite number of potential contexts in which WP_Query could be called.  We need something more.

-Mike

_______________________________________________
wp-hackers mailing list
[hidden email]
http://lists.automattic.com/mailman/listinfo/wp-hackers
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Filters on get_posts()

scribu-2
On Mon, Oct 11, 2010 at 9:03 PM, Mike Schinkel
<[hidden email]>wrote:

> On Oct 11, 2010, at 10:50 AM, scribu wrote:
> > Context is already provided: the wp_query object itself. This was only
> > introduced in WP 2.9 so most plugins still have to catch up.
>
>  A binary property like 'caller_get_posts'  cannot capture the infinite
> number of potential contexts in which WP_Query could be called.  We need
> something more.
>

Ok, and how would that "something more" look like? Something that couldn't
already be captured in WP_Query.
_______________________________________________
wp-hackers mailing list
[hidden email]
http://lists.automattic.com/mailman/listinfo/wp-hackers
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Filters on get_posts()

Mike Schinkel-5
On Oct 11, 2010, at 2:36 PM, scribu wrote:
>
> Ok, and how would that "something more" look like? Something that couldn't
> already be captured in WP_Query.

Here is one potential that I referenced in my email to John:

http://core.trac.wordpress.org/ticket/15063

It's a starting point for which we'd need core to leverage and as a best practice for plugin developers, to really be useful.  

-Mike


_______________________________________________
wp-hackers mailing list
[hidden email]
http://lists.automattic.com/mailman/listinfo/wp-hackers
Loading...