WordPress: Why Isn't add_rewrite_rule Working?

2019-08-05 20:08发布

问题:

Goal

A visible URL of:

/products/building-automation/details/productSKU

Should point to the real WordPress page of:

/products/details/?SKU=productSKU

Code

public function setup_frontend() {

    add_rewrite_rule(
        'products/(building-automation|lighting-controls)/details/([^/]*)',
        'products/details/?SKU=$matches[2]',
        'top'
    );

    // Other code logic...

}

From what I can tell, the $matches points to the portions of the regex that are in (), so in the example, $matches[1] would be building-automation, and $matches[2] would be productSKU.

I have tried the flushing the rules, many times. This is being called from inside a class, but that doesn't appear to be the issue. I'm attaching the function to the init event.

What is Happening

I am getting the 404 template. What am I doing wrong?

Edit

Turns out, the second part of the parameter HAS to be index.php. Since I was trying to point to products/..., it broke. So I've updated to this:

    add_rewrite_rule(
        'products/(building-automation|lighting-controls)/details/([^/]*)',
        '?pagename=products/details&SKU=$matches[2]',
        'top'
    );

It's not working and point to the right page and template. However, the $matches part is still not coming through. In fact, $_GET['SKU'] is coming through as '$matches[2]'.

回答1:

The first problem is that it's pointing to something that doesn't start with index.php. It has to point to index.php?stuff, unfortunately. But you can still use the page name, as shown below.

add_rewrite_rule(
    'products/(building-automation|lighting-controls)/details/([^/]*)',
    'index.php?pagename=products/details&SKU=$matches[2]',
    'top'
);

Second, you need to register your query string, which is SKU. Add this:

add_filter( 'query_vars', 'product_details_rewrite_filter' );

function product_details_rewrite_filter( $query_vars ){
    $query_vars[] = 'SKU';
    return $query_vars;
} 

You will still have a problem. $_GET['SKU'] will be $matches[2], not RIBU1C. To fix this, change $matches[2] to $2. Then it will work:

add_rewrite_rule(
    'products/(building-automation|lighting-controls)/details/([^/]*)',
    'index.php?pagename=products/details&SKU=$2',
    'top'
);


回答2:

It doesn't work in this way... You trying to achive impossible with this code. Rewrites Rules in wordpress work with index.php routing, but not external pathes. So

products/(building-automation|lighting-controls)/details/([^/]*)

should be "translatable" to "wordpress" language (something like)

index.php?post_type=products&category=$matches[1]&scu=$matches[1]

notice, scu should also be defined as extra var.

edit 1: Thing (I think) you trying to achive is really looks like a htaccess rule pattern, in this case you can use mod_rewrite_rules filter (it filter content that goes to .htaccess) to change it as you like it.

edit 2: Advertisment - you can also use my debug bar plugin called debug bar rewrite rules to basically debug this data. Notice: (currently it doesn't support rules list via add_rewrite_rule, so you can only visually inspect rule, and see if it matches your expectation).



回答3:

1) Try to update permalinks.

Go to Dashboard->Setting->Permalinks-> button "Save changes"

2) Add action to your function

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

add_rewrite_rule(
    'products/(building-automation|lighting-controls)/details/([^/]*)',
    'products/details/?SKU=$matches[2]',
    'top'
);

// Other code logic...

}