Custom query_var causes displaying posts archive on front page

After detailed debugging of WP::parse_request() and WP_Query::parse_query() I found out that unset( $query_vars['date'] ); in 'request' filter helps.

It basically unsets date query var before WP_Query::parse_query() is invoked so is_home() returns false.

add_filter( 'request', function( $query_vars ) {
        global $wp_query, $wp;

        if ( ! $wp_query->is_main_query() ) {
            return $query_vars;
        }

        $qv_keys = array_keys( $wp->query_vars );

        if ( ! ( in_array( 'product_cat', $qv_keys, true )
           || in_array( 'product_tag', $qv_keys, true )
           || in_array( 'post_type', $qv_keys, true ) && 'product' === $wp->query_vars['post_type']
           || in_array( 's', $qv_keys, true )
        ) ) {
            unset( $query_vars['date'] );
        }

        return $query_vars;
} );

Explanation:

Posts archive loads when WP_Query::$is_home = true so I traced back places where this value is set and in brief I think it’s like this:

  1. $this->query_vars['post_type'] and $this->query_vars['name'] are not set in this condition as date query var is not assigned with any post type.
  2. In result after many operations WP_Query::$is_singular is set to false here
  3. And it leads to WP_Query::$is_home = true.

Leave a Comment