1

I have these slugs on my website

http://www.domain.com/about (standard WP page)
http://www.domain.com/custom-slug (not a WP page, post or custom post type)

I'm trying to develop a rewrite rule to match the latter scenario, to redirect them to my custom plugin so I can render content for them. My rewrite rule looks like this

add_rewrite_rule('^(.*)/?', 'index.php?pagename=special-page&id=$matches[1]', 'bottom');

By setting it to 'bottom' it kicks in after all other WordPress rewrite rules, and so won't get processed - WordPress will send a request for /custom-slug to the 404 page.

If I set the rewrite rule to 'top' then every page on WordPress will be matched. That would be ok if my rewrite rule executed and it checked in a custom database table to see if /custom-slug is a valid slug in my custom system. If it does then render content for it. If it doesn't to have WordPress continue on trying to make a match for it (redirect /about to the actual about page on the site)

Normally rewrite rules are more straightforward where you match a specific keyword in the URL following by a string after it, but that won't work for me - all slugs will look the same.

Any ideas on how best to accomplish this?

2

You can't do that with a rewrite rule, the regular page rule already matches, but you can intercept the data that's extracted from that rule before it gets transformed into a query.

We do that by hooking the parse_request action, where we can check for a custom slug, and modify the request object directly. I recommend you var_dump($query) and have a look at the whole object for different kinds of requests. See comments in code.

add_action( 'parse_request', 'wpd_check_for_my_custom_slug' );
function wpd_check_for_my_custom_slug( $query ) {
    if( isset( $query->query_vars['pagename'] ) ){
        // check if the slug matches some custom content
        // replace this with your query code
        if( 'my-custom-slug' == $query->query_vars['pagename'] ){
            // the request is for a custom slug
            // store the originally requested slug
            $query->query_vars['my_special_var'] = $query->query_vars['pagename'];
            // and load a placeholder page
            $query->query_vars['pagename'] = 'placeholder-page';
        }
    }
}

Note that if your permalink structure is just %postname%, the slug will be in name, not pagename. You will then also have to unset name after.

If you plan to load a theme file at the end of this process, I suggest using a placeholder page of the page post type for these requests. WordPress expects some kind of post object to exist for a template to successfully render. You can filter and override all of the titles, content, etc..

If you plan on outputting something completely custom, you could load that and just exit here.

  • Excellent! I had not considered the parse_request action - very powerful and exactly what I need. Thank you for the detailed answer. – sceilig Apr 21 '18 at 5:57

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.