最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

permalinks - WordPress thinks my custom route is a 404

programmeradmin0浏览0评论

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/path/:id where :id is a dynamic value corresponding to a post id, so the URL could be domain/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?

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/path/:id where :id is a dynamic value corresponding to a post id, so the URL could be domain/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?

Share Improve this question asked Jun 1, 2016 at 12:03 AhrengotAhrengot 4425 silver badges14 bronze badges 5
  • Did you flush your rewrite rules? codex.wordpress/Function_Reference/flush_rewrite_rules – jgraup Commented Jun 1, 2016 at 13:30
  • Yes. Flushed the rewrite rules. Both manually and in the plugin's activation hook. – Ahrengot Commented Jun 2, 2016 at 10:16
  • Rewrite rules have to result in a successful main query. If my_custom_url is not the slug of an actual page, you will get a 404. If some_id is a valid post ID, then set the correct native query vars with that ID so the query succeeds. – Milo Commented Mar 1, 2017 at 16:08
  • That's just not always an option. For instance, if I want to provide a "My profile" frontend page for my users where they can update basic information about themselves. There's no post associated with such a page, but I still need a URL for it. In any case, I figured out a solution and posted my answer below. – Ahrengot Commented Mar 1, 2017 at 19:27
  • 1 Here's an example of an approach that short-circuits the query parsing phase and doesn't produce a query that's just doomed to fail. – Milo Commented Mar 2, 2017 at 4:27
Add a comment  | 

2 Answers 2

Reset to default 3

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.

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/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/Rareloop/router

发布评论

评论列表(0)

  1. 暂无评论