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

rewrite rules - Case-insensitive add_rewrite_rules in Wordpress functions

programmeradmin0浏览0评论

Been hitting my head against the wall on this for a while. If I have a add_rewrite_rules like so:

    $aNewRules = array('my-books/?$'  => 'index.php?pagename=my-books');

This works correctly; going to / shows .php?pagename=my-books.

However, this is case sensitive - going to "/My-bOoKs/" does not trip the rule (and thus shows the 404 page instead).

Is there an easy way to just mark it as case insensitive? I only make links with the lower case, sure, but users may add a capital on their own and I'd hate to lose the traffic to a 404 page.

Thanks! Alex

Been hitting my head against the wall on this for a while. If I have a add_rewrite_rules like so:

    $aNewRules = array('my-books/?$'  => 'index.php?pagename=my-books');

This works correctly; going to http://example/my-books/ shows http://example/index.php?pagename=my-books.

However, this is case sensitive - going to "/My-bOoKs/" does not trip the rule (and thus shows the 404 page instead).

Is there an easy way to just mark it as case insensitive? I only make links with the lower case, sure, but users may add a capital on their own and I'd hate to lose the traffic to a 404 page.

Thanks! Alex

Share Improve this question asked May 23, 2016 at 21:22 Alex GoldAlex Gold 1612 bronze badges 6
  • If you want to achieve such thing you'll have to add a rewrite rule for each assumption e.g My-bOoKs, My-books, etc .. but the perfect solution here I guess is to redirect those to the normal pagename 'my-books'.. – Ismail Commented May 23, 2016 at 21:43
  • @SamuelElh - At that point, I could do something more like '[Mm][Yy]-[Bb][Oo][Oo][Kk][Ss]/?$' . . . but I have a lot of these rules in place, so I'd like something a bit less tedious of possible :). – Alex Gold Commented May 23, 2016 at 21:57
  • That totally does it! why not implement that one? – Ismail Commented May 23, 2016 at 22:00
  • Just because it's messy and tedious - if there's no other way, I'll do that, but I was hoping there's a simple tag (like '?i' or something) I could add to do that instead - I've found a number of things online with [NC] or some "i" related tag that is meant to do this in Regex, just can't get any of them to work in Wordpress at this level :). – Alex Gold Commented May 23, 2016 at 22:02
  • 1 Haha, yeah - I'd rather just use the brackets :D – Alex Gold Commented May 23, 2016 at 22:27
 |  Show 1 more comment

2 Answers 2

Reset to default 2

As the answer below mentions, it is not possible to pass a flag to add_rewrite_rule(); however, it is possible to use an inline modifier. In your example, you would do this:

$aNewRules = array('(?i)my-books/?$' => 'index.php?pagename=my-books');

(note the (?i) in the regular expression).

The advantage of this approach is that your rewrite rules are much cleaner and more performant.

See this page on regular expression modifiers for more information.

Not directly. The wordpress API is using preg_match / preg_replace but is not exposing the flags parameter. That's what you'd need to pass the insensitive flag (i).

See their implementation here: https://github/WordPress/WordPress/blob/a8802232ecac8184cbe6e8dbe9c6a7bd0f5b7dee/wp-includes/class-wp-rewrite.php

Probably the simplest solution is just to use a little helper function to do this for you:

function anyCase($rules){
    $insensitive = array();
    foreach ($rules as $regex => $mapping) {
      $regex = preg_replace_callback('([A-Za-z])', function($matches){
            return "[" . strtoupper($matches[1]) . strtolower($matches[1]) . "]";
      }, $regex);
      $insensitive[$regex] = $mapping;
    }
    return $insensitive;
  }

Given

$rules = array('my-books/?$'  => 'index.php?pagename=my-books');
var_dump(anyCase($rules));

Will output array(1) { ["[Mm][Yy]-[Bb][Oo][Oo][Kk][Ss]/?$"]=> string(27) "index.php?pagename=my-books" }

So you can keep your rules clean / simple :-)

If you're running an older PHP that doesn't support closures you can just this instead:

  function lowerOrUpper($matches){
    return "[" . strtoupper($matches[0]) . strtolower($matches[0]) . "]";
  }

  function anyCase($rules){
    $insensitive = array();
    foreach ($rules as $regex => $mapping) {
      $regex = preg_replace_callback('([A-Za-z])', lowerOrUpper, $regex);
      $insensitive[$regex] = $mapping;
    }
    return $insensitive;
  }

Cheers

发布评论

评论列表(0)

  1. 暂无评论