conditional tags - What is the correct method for determining 'is_front_page' when using filters such as &#3

admin2025-06-02  2

On my site several filters should be applied if the user is viewing the static home page. My understanding is that is_front_page() should determine if that is indeed the case.

However, whenever I use the function I find that sometimes it returns true (e.g. posts_orderby) but mostly it returns false (e.g. pre_get_posts, posts_fields, posts_join and posts_where). Regardless of the result though, I always recieve the following notice -

Trying to get property of non-object in {my_path}\wp-includes\query.php on line 4373

The method containing the offending line is WP_Query::is_front_page() -

public function is_front_page() {
    // most likely case
    if ( 'posts' == get_option( 'show_on_front') && $this->is_home() )
        return true;
    /** The offending line */ elseif ( 'page' == get_option( 'show_on_front') && get_option( 'page_on_front' ) && $this->is_page( get_option( 'page_on_front' ) ) )
        return true;
    else
        return false;
}

To combat this issue I have created my own function, as below, but it seems "dirty" to have had to do so. So my question is thus - is there a better way to do this?

function fgw_is_front_page($q){

    if(!is_a($q, 'WP_Query'))
        return false;

    return (get_option('show_on_front') == 'page' && get_option('page_on_front') && $q->get('page_id') == get_option('page_on_front'));

}

Edit

Afer further investigation it seems that the offending line is actually 4369 (wp-includes/querey.php) - $page_obj = $this->get_queried_object();

$page_obj is being returned as null, meaning that check for $q->is_front_page() fails. This seems wrong, and unless anyone is able to explain how this could in any way be expected behaviour I'll look at opening a ticket on Trac.


Update

I have now amended the above function. Making use of the second argument passed to all of the filters that I am using (the WP_Query instance), as mentioned by @birgire, has allowed me to do away with the global.

However, taking the below example, I am still receiving the aformentioned notice (and result of false) when checking $q->is_front_page() -

add_filter('posts_fields','fgw_index_posts_fields', 10, 2);
function fgw_index_posts_fields($fields, $q){
    
    global $wpdb;

    if(!is_admin() && is_main_query() && (is_home() || $q->is_front_page($q)))
        $fields.= $wpdb->prepare(', %1$s.name as category_name', $wpdb->terms);
    
    return $fields;
    
}

Replacing $q->is_front_page() with fgw_is_front_page($q) works, but again it feels dirty to have to use a custom solution when seemingly there is one that already exists.

On my site several filters should be applied if the user is viewing the static home page. My understanding is that is_front_page() should determine if that is indeed the case.

However, whenever I use the function I find that sometimes it returns true (e.g. posts_orderby) but mostly it returns false (e.g. pre_get_posts, posts_fields, posts_join and posts_where). Regardless of the result though, I always recieve the following notice -

Trying to get property of non-object in {my_path}\wp-includes\query.php on line 4373

The method containing the offending line is WP_Query::is_front_page() -

public function is_front_page() {
    // most likely case
    if ( 'posts' == get_option( 'show_on_front') && $this->is_home() )
        return true;
    /** The offending line */ elseif ( 'page' == get_option( 'show_on_front') && get_option( 'page_on_front' ) && $this->is_page( get_option( 'page_on_front' ) ) )
        return true;
    else
        return false;
}

To combat this issue I have created my own function, as below, but it seems "dirty" to have had to do so. So my question is thus - is there a better way to do this?

function fgw_is_front_page($q){

    if(!is_a($q, 'WP_Query'))
        return false;

    return (get_option('show_on_front') == 'page' && get_option('page_on_front') && $q->get('page_id') == get_option('page_on_front'));

}

Edit

Afer further investigation it seems that the offending line is actually 4369 (wp-includes/querey.php) - $page_obj = $this->get_queried_object();

$page_obj is being returned as null, meaning that check for $q->is_front_page() fails. This seems wrong, and unless anyone is able to explain how this could in any way be expected behaviour I'll look at opening a ticket on Trac.


Update

I have now amended the above function. Making use of the second argument passed to all of the filters that I am using (the WP_Query instance), as mentioned by @birgire, has allowed me to do away with the global.

However, taking the below example, I am still receiving the aformentioned notice (and result of false) when checking $q->is_front_page() -

add_filter('posts_fields','fgw_index_posts_fields', 10, 2);
function fgw_index_posts_fields($fields, $q){
    
    global $wpdb;

    if(!is_admin() && is_main_query() && (is_home() || $q->is_front_page($q)))
        $fields.= $wpdb->prepare(', %1$s.name as category_name', $wpdb->terms);
    
    return $fields;
    
}

Replacing $q->is_front_page() with fgw_is_front_page($q) works, but again it feels dirty to have to use a custom solution when seemingly there is one that already exists.

Share Improve this question edited Jun 15, 2020 at 8:21 CommunityBot 1 asked May 14, 2015 at 9:54 David GardDavid Gard 3,3105 gold badges26 silver badges39 bronze badges
Add a comment  | 

2 Answers 2

Reset to default 5

Regarding the posts_orderby, posts_where, posts_join and posts_clauses hooks, the current \WP_Query object is available through the second input argument.

These are the relevant parts from the \WP_Query class:

$orderby = apply_filters_ref_array( 'posts_orderby', array( $orderby, &$this ) );
$where   = apply_filters_ref_array( 'posts_where', array( $where, &$this ) );
$join    = apply_filters_ref_array( 'posts_join', array( $join, &$this ) );
$clauses = (array) apply_filters_ref_array( 'posts_clauses', array( compact( $pieces ), &$this ) );

all using the apply_filters_ref_array function and &$this is the current \WP_Query instance. The Codex says the following about this function:

This function is identical to apply_filters, but the arguments passed to the functions hooked to $tag are supplied using an array.

You can access the second argument with for example:

add_filter( 'posts_where', function( $where, \WP_Query $q )
{
    if( $q->is_front_page() ) <-- This method won't work here with a static front-page!!!
    {
        // ...
    }
}, 10, 2 );

so you don't have to rely on the global $wp_query object.

After tracing this inside WP_Query, we've found the reason why calling the is_front_page() method doesn't work inside these filter callbacks. There problem lies within the is_page() method that tries to use the get_queried_object() method that still hasn't got an object to return.

The is_home() method works on the other hand, and it isn't calling the is_page() method.

Update:

There seems to be at least two Trac tickets, #27015 and #21790, that related to this problem.

In #27015 there's a suggested patch by @mattonomics, that modifies the queried_object object within the parse_query() method.

So why not try these modifications in our case, but through the parse_query hook instead:

/**
 * A workaround for the is_front_page() check inside pre_get_posts and later hooks.
 *
 * Based on the patch from @mattonomics in #27015
 *
 * @see http://wordpress.stackexchange/a/188320/26350
 */

add_action( 'parse_query', function( $q )
{
    if( is_null( $q->queried_object ) && $q->get( 'page_id' ) )
    {
        $q->queried_object    = get_post( $q->get( 'page_id' ) );
        $q->queried_object_id = (int) $q->get( 'page_id' );
    }
} );

We should be able to add further changes this way, from that patch.

instead of

$query->is_front_page()

try using

$query->get('page_id') == get_option('page_on_front')

(in context:)

function custom_pre_get_posts( $query ) {
    if ( $query->get('page_id') == get_option('page_on_front') ) {
        // do stuff
    }
}
add_action('pre_get_posts', 'custom_pre_get_posts');

This solution is from here: https://core.trac.wordpress/ticket/21790#comment:11

转载请注明原文地址:http://conceptsofalgorithm.com/Algorithm/1748858626a314309.html

最新回复(0)