Question

I created a plugin that sets up a custom route and then loads a template file for that url. Everything works fine, except that WordPress seems to think it's a 404 even though it's correctly rendering my template.

For instance it says 404 in the document title and an error404 class is added to <body>

The custom url is domain.com/path/:id where :id is a dynamic value corresponding to a post id, so the URL could be domain.com/path/275. In the example below some_id is used as the post id variable.

Here's a reduced version of my plugin:

<?php

class MyPlugin {
  public function __construct() {
    add_action( 'init', array($this, 'add_response_endpoint') );
    add_filter( 'template_include', array($this, 'add_response_template') );
  }

  public function add_response_endpoint() {
    add_rewrite_rule(
      '^path/([0-9]+)/?',
      'index.php?pagename=my_custom_url&some_id=$matches[1]',
      'top'
    );

    add_rewrite_tag('%some_id%', '([^&]+)');
  }

  public function add_response_template($template) {
    if ( get_query_var( 'pagename' ) === 'my_custom_url' ) {
      $template = trailingslashit( dirname( __FILE__ ) ) . 'templates/custom-page-template.php';
    }

    return $template;
  }
}

new MyPlugin();

Am I missing something here? Or should I start looking for this bug elsewhere?

Était-ce utile?

La solution

Manually setting is_404 = false; fixed my issue. However I'm not sure this is the best way to do it. I tried using the pre_get_posts filter instead without any luck.

Anyway, for anyone else in the same boat, you can do this to get rid of the 404 state:

public function add_response_template($template) {
  global $wp_query;
  if ( 'my_custom_url' === get_query_var( 'pagename' ) ) {
    $wp_query->is_404 = false;
    $template = trailingslashit( dirname( __FILE__ ) ) . 'templates/custom-page-template.php';
  }

  return $template;
}

And to update the document title (The stuff inside <title> in the <head> section) here's a snippet for making that work nicely too.

add_filter( 'document_title_parts', function($title_arr) {
  if ( 'my_custom_url' === get_query_var('pagename') ) {
    $title_arr['title'] = "Document title for my custom route";
  }

  return $title_arr;
}, 10, 1 );

If anyone knows of a better way please let me know.

Autres conseils

I have not found custom routes in WP mature enough. I suggest you use any of the 3 routes solutions mentioned in Timber docs. https://timber.github.io/docs/v2/guides/routing/

if you use Upstatement library (https://github.com/Upstatement/routes) you would do:

Routes::map('info/:name/page/:pg', function($params){
    //make a custom query based on incoming path and run it...
    $query = 'posts_per_page=3&post_type='.$params['name'].'&paged='.intval($params['pg']);

    //load up a template which will use that query
    Routes::load('archive.php', null, $query, 200);
});

See the 200 in Routes::load, that sends the proper header.

If you need something more versatile use Rareloop router https://github.com/Rareloop/router

Licencié sous: CC-BY-SA avec attribution
Non affilié à wordpress.stackexchange
scroll top