0

In a nutshell what I want to achieve is this:

If slug equals foobar serve the foobar.php template.

I know I could do this with page-foobar.php but I don't want to create a page for this.

add_action('init', 'template_suggestions');
function template_suggestions() {

  global $wp;

  $current_slug = add_query_arg([], $wp->request);

  if ($current_slug == 'foobar') {

    // No, don't server the 404.php.
    // Serve foobar.php.
    // But how?
    // Big question mark.
  }
}
1

Got it! But this is a dirty thing. As it won't take care of pagination and underlying queries. If you need a bit more of WordPress' logic behind that custom route, please check the answer linked in the comments. But if you just need to serve one static page, this probably is a good starting point:

add_action('template_include', 'template_suggestions');
function template_suggestions($template) {

  global $wp;

  $current_slug = $wp->request;

  $foobar_template = locate_template(['foobar.php']);

  if ($current_slug == 'foobar' && $foobar_template != '') {

    // Prevent 404.
    status_header(200);

    return $foobar_template;
  }

  return $template;
}

Source Don’t use template_redirect to load an alternative template file


Since I use Yoast I had to use wpseo_title instead of document_title_parts or pre_get_document_title to set the title accordingly.

add_filter('wpseo_title', 'template_suggestions_titles', 10, 1);
function template_suggestions_titles() {

  global $wp;

  $current_slug = $wp->request;

  if ($current_slug == 'foobar') {

    return 'Foobar';
  }
}
  • That add_query_arg is unnecessary. The slug is just $wp->request. – Jacob Peattie Mar 11 at 12:53
  • Is /foobar an actual Page, Post, Custom Post Type, Archive, etc? If not and this is a slug that has no underlying structure matching rewrite rules, you'd need to add a rewrite rule OR you could pre_get_posts and $query->is_404 = false. Although you my need to do some other things to avoid any screwy data within the main query. Another option is for you to hook into do_parse_request and circumvent the main query and thus your status_header(200) should suffice. Or further down the request chain into request hook you can knock out the $query->query_vars['error']` value which is 404. – Adam Mar 11 at 13:11
  • 1
    Right, I see now... You have no underlying object type. Take a look at another question to which I post an answer to achieve the very thing you are after here: wordpress.stackexchange.com/q/67732/13418 – Adam Mar 11 at 13:14
  • @userabuser – Yes, no underlying object. Do I really have to take care of so much more? I mean, I have a 200 status now, I have my template, it's just the page title that's missing and which doesn't seem to be settable via the usual hooks. Ah yeah, because I use Yoast and then that's wpseo_title. – leymannx Mar 11 at 13:21
  • 1
    Well.. not necessarily "all that". Hook into pre_get_posts or request or do_parse_request if you would like and alter the query var $query->is_404 = false (or whatever the accessible query vars are available to you). It's showing 404 because WP has set the 404 based on there being no rewrite. Buuut... if you are successfully returning a 200, just hook into wp_title and check for $current_slug == 'foobar' and filter the result based on that context. Dirty, but will do the job. – Adam Mar 11 at 13:43

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.