3

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
3
  • 1
    Post the code you're using at the moment. Commented Apr 11, 2015 at 10:23
  • @TheDeadMedic thought this would be enough ;) However check current answer by websupporter This one doesn't work on my installation either and this is with all other plugins deactivated aside from the one-file-plugin he wrote and appears to be working on his end.
    – Sam
    Commented Apr 15, 2015 at 7:43
  • The .htaccess won't be interfering, I assure you. This just maps all non-file/directory requests to index.php. Commented Apr 15, 2015 at 8:17

2 Answers 2

3
+100

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:

6
  • OK, so I was able to test this now and sadly I get literally the same result as on my tries. Here's what I did: I copied your content to myplugin.php inside /plugins and activated the plugin on the backend. After activation i went to Setting > Permalinks and pressed Save Changes to flush the rewrite rules. I then created a new page using the shortcode [myplugin]. I went to my installation foo.dom/myplugin/123 => it redirected me to foo.dom/myplugin/ and the output was filter: - no more. :'( There's no other rewrite stuff ongoing, I disabled my plugin. My htaccess is default,too
    – Sam
    Commented Apr 15, 2015 at 7:38
  • thats quite strange to be honest. can you try it locally on a complete clean installation? i know, you say, nothing is going on, but it works for me. this is why i am puzzled. "I then created a new page using the shortcode [myplugin]" you mean, you have created a new page and in there, you used the shortcode, right? Commented Apr 15, 2015 at 8:14
  • Sad news... here's what I did: Download WP (4.1.1), extract, copy myplugin.php // cd wp-dir // php -S localhost:9090 Create new Page with the given shortcode as body content. Synchronize page id within myplugin.php Enable Plugin on backend // go to Settings > Permalinks and save them a few times ("Post Name" setting) foo.dom/myplugin/123 redirects to foo.dom/myplugin with no filter being displayed.
    – Sam
    Commented Apr 15, 2015 at 8:35
  • the rewrite_rule() is set to 'top', right? check your rules with wordpress.org/plugins/rewrite-rules-inspector if they are placed correctly. running out of ideas :/ Commented Apr 15, 2015 at 11:52
  • 1
    ouch! i should have thought of this, when you wrote 'page' instead of 'post'. Glad it works :) Commented Apr 15, 2015 at 13:06
1

I would use the add_rewrite_rule() function, please note that the code is untested but it should work depending on your specific use. If you also need to set a post_id, just add it to the index.php?p=X... string.

function myplugin_filter_add_rewrite_rules()
{
  // Allow for /myplugin/filter/someFilter
  add_rewrite_rule('myplugin/filter/([^/]+)/?$',
   'index.php?filter=$matches[1]',
   'top');

  // Optionally keep pagination /myplugin/filter/someFilter/page/2
  add_rewrite_rule('myplugin/filter/([^/]+)/page/([0-9]+)?$',
   'index.php?filter=$matches[1]&paged=$matches[2]',
   'top');
}

add_filter('init', 'myplugin_filter_add_rewrite_rules');

As already stated, don't forget to flush the rules by visiting Settings > Permalinks or use flush_rewrite_rules() in the plugin activation (don't execute it at every page load).

1
  • Hey gyo, please see what I wrote under websupporters answer. I begin to think that the problem may be completely elsewhere as his solution doesn't work in my place with all other plugins deactivated aside from his. Added my .htaccess into the question as well, I'm really getting more n more clueless about this.
    – Sam
    Commented Apr 15, 2015 at 7:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.