7

I have static front page for my WP installation set from settings > reading. Then I have added a URL endpoint using.

add_rewrite_endpoint('foo', EP_ALL);

So, the front page should be accessible via

http://example.com/
http://example.com/foo
http://example.com/foo/bar

For #1 Everything works fine but for #2 and #3 default home.php is shown instead of static home page. Tested locally in both single and multisite installation.

Is it a desired behavior or I hit something unusual? More importantly how can I make WP to show the static homepage in the given condition?

Solution

I was already hooking into parse_request to process part of code if foo exists. so, as per @gmazzap's solution. I only need to unset it afterwards. No need for extra hooked function is needed to bypass the bug.

add_action('parse_request', function(&wp){

    $key = 'foo';

    if (!array_key_exists( $key, $wp->query_vars ) ) {
        return;
    }

    // do things when foo exists

    // we no longer need 'foo'
    unset($wp->query_vars[$key]);

});
  • 3
    Will be fixed in 4.3. – fuxia Jun 17 '15 at 12:54
  • 1
    ah, okey. Its a bug then. Ticket opened for 22 months! I am just glad it is fixed! – Sisir Jun 17 '15 at 13:07
4

Maybe I did not get this very well, but if you need to just remove 'foo' from query vars would not be much more simple to use the 'request' filter and remove the var from there?

Code needed:

add_filter('request', function($query_vars) {
     return array_diff_key($query_vars, array('foo'=>''));
});

It:

  • runs on main query only
  • remove the var for $wp object
  • acts before the query is set on $wp_query, so no need to remove the query from there
  • does not affect all the other variables

Edit:

A problem of this code is that it runs very early, so that it will be hard to catch the presence of the query variable and do something based on its presence / value.

A solution may be the run the conditions on the same 'request' filter, just before remove the query var (e.g. using same hook with higer priority).

Another solution may be add a flag to $wp object:

add_filter('request', function($query_vars) {
     $GLOBALS['wp']->_foo = isset($query_vars['foo']) ? $query_vars['foo'] : false;
     return array_diff_key($query_vars, array('foo'=>''));
});

After that, would be possible to check the 'foo' variable in any hook fired after 'request', the earliest is 'parse_request'

add_action('parse_request', function($wp) {
    $foo = $wp->_foo;
    // do something with foo
});

The last is 'shutdown':

add_action('shutdown', function() {
    $foo = $GLOBALS['wp']->_foo;
    // do something with foo
});
  • Will this remove foo from $wp->query_vars on parse_request action? I am running conditional code on parse_request when foo exists. – Sisir Jun 18 '15 at 5:01
  • @Sisir yes, as you can see in source core.trac.wordpress.org/browser/tags/4.2.2/src/wp-includes/… 'request' hook is fired the line before 'parse_request'. You can move your condition to request hook, or maybe use 'parse_request' to remove the variable, just after you did something based on 'foo' presence. I also edited the A to include a third approach. – gmazzap Jun 18 '15 at 7:52
  • Spot on! As I am already hooking into parse_request. Removing foo from the query var after I am done with it seems more appropriate. I only need unset($wp->query_vars['foo']); just before I quit my hooked function in parse_request. Thanks for your help on this. – Sisir Jun 18 '15 at 9:37
4

This is a bug 25143 as @toscho pointed out and will be fixed in 4.3

Workaround Found in the ticket and modified a little

WordPress adds foo as query var that causes the problem. So, we need to remove it before WP query the DB

add_action( 'pre_get_posts', 'wpse191771_unset_query_arg' );
function wpse191771_unset_query_arg($query){

    if ( is_admin() || ! $query->is_main_query() ) {
        return;
    }

    $key = 'foo';

    $query_vars =& $query->query_vars;

    if ( array_key_exists($key, $query_vars) ) {
        // unset ref var from $wp_query
        $query->set( $key, null );

        global $wp;
        // unset ref var from $wp
        unset( $wp->query_vars[ $key ] );

        // if in home (because $wp->query_vars is empty) and 'show_on_front' is page
        if ( empty( $wp->query_vars ) && get_option( 'show_on_front' ) === 'page' ) {
            // reset and re-parse query vars
            $wp->query_vars['page_id'] = get_option( 'page_on_front' );
            $query->parse_query( $wp->query_vars );
        }
    }

}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.