I’m really stuck on the WP_Rewrite functionality…

What I have

I have a plugin that’s rendered using a shortcode and is displaying full-site content. E.g.:

//?p=2 (maps to domain.tld/myplugin/)
[my-plugin]

This plugin basically is a directory of some list-content.

What I want

Basically I want to achieve nice urls for the categorisation of the list content displayed by the plugin. E.g.:

domain.tld/myplugin/?filter=someFilter // works but is ugly

domain.tld/myplugin/someFilter         // is what I want

What I tried

So I’ve tried the approach using add_rewrite_rule as well as modifying:

global $wp_rewrite

$customRules = [
    "myplugin/([^/]+)/?" => "?p=2&filter=$matches[1]" // try 1.1
    "myplugin/([^/]+)/?" => "/myplugin/filter=$matches[1]" // try 2.1
];

$wp_rewrite->rules = $customRules + $wp_rewrite->rules; // try 1
$wp_rewrite->extra_rules_top = $customRules + $wp_rewrite->extra_rules_top // try 2

However none of my rewrites work. The best I can achieve is to simply get redirected to /myplugin/ without any parameter added to the page. This, I assume, is due to WordPress matching ?p=2 to /myplugin/ as defined within the permalink structure of the page. So my guess is that parameters simply are stripped from the rule.

So my question:

How can I achieve what I want? Do I really have to write the rewrite-rules hard into the .htaccess?

The 50% solution

So after reading this awesome article I was able to get at least something working. Ultimately I’m able to achieve

domain.tld/myplugin/filter/someFilter
a syntax like "param/value"

This is done by add_rewrite_endpoint() and adding the filter to the query_vars. For now this thing is what I do but ultimately I’d really like to get it down to:

domain.tld/myplugin/someFilter

So help will still be much appreciated 😉

Update 1st solution by @websupporter

Tried the approach given by a user here and it still doesn’t work. I deactivated all plugins and it still doesn’t work.

The only thing that could interfere at this point as far as I know is the .htaccess but to me this one looks pretty standard as well..

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>

# END WordPress

2 Answers
2

This approach should work for you:

<?php
/**
 * Plugin Name: Rewrite Shortcode
 **/

 add_shortcode( 'myplugin', 'mp_shortcode' );
 function mp_shortcode(){
    return '<p>Filter: ' . get_query_var( 'filter' ) . '</p>';
 }

 add_action( 'init', 'mp_rewrite' );
 function mp_rewrite(){
    $post_id = 2;
    add_rewrite_rule( 'myplugin/([^/]+)/?$', 'index.php?p=' . $post_id . '&filter=$matches[1]', 'top' );
    add_rewrite_tag( '%filter%', '([^/]+)' );
 }
?>

I developed it quickly as a small plugin, so I was able to test it myself. While you work with the global $wp_rewrite I thought it might be better to use the functions, which are documented in the Codex. Basically just, because I know them better 🙂 So I can’t exaktly tell, what you did wrong, but I can tell, what I do differently.

You’re approach:

"myplugin/([^/]+)/?" => "?p=2&filter=$matches[1]

I’ve explicitly told WordPress to use the index.php as it is also done in the documents. And I use add_rewrite_tag() to generate a new query variable, which I can read with get_query_var() in my shortcode.

Attention: Flush the Rules!
When you use these functions, you have to go to Settings > Permalinks and click the “update”-button. If you don’t do this, the new rules won’t be active. You could also use flush_rewrite_rules() during the activation of the plugin. An example on how to do this is given in the Codex.

Docs:

  • https://codex.wordpress.org/Rewrite_API/add_rewrite_rule
  • https://codex.wordpress.org/Rewrite_API/add_rewrite_tag
  • https://codex.wordpress.org/Function_Reference/flush_rewrite_rules

Leave a Reply

Your email address will not be published. Required fields are marked *