Per Søderlind

I code for fun

  1. how-to
  2. WordPress plugins and permalinks, how to use pretty links in your plugin

WordPress plugins and permalinks, how to use pretty links in your plugin

I’m working on a plugin, Read Offline, and one of the wishes was for url friendly links. After intensive googling, here’s how I did it:

“My Permalink Demo” plugin:

Plugin Name: My Permalink Demo
Plugin URI:
Description: Demo plugin to show how to implement your custom permalink for your plugin. To test, add the [mypermalink] or [mypermalink val=”ipsum”] shortcode to a page or post.
Version: 1.0.1
Author: Per Soderlind
Author URI:

if (!class_exists(‘my_permalink’)) {
class my_permalink {

function __construct(){
// demo shortcode
add_shortcode(‘mypermalink’, array(&$this,’my_permalink_demo_shortcode’));

// permalink hooks:
add_filter(‘generate_rewrite_rules’, array(&$this,’my_permalink_rewrite_rule’));
add_filter(‘query_vars’, array(&$this,’my_permalink_query_vars’));
add_filter(‘admin_init’, array(&$this, ‘my_permalink_flush_rewrite_rules’));
add_action(“parse_request”, array(&$this,”my_permalink_parse_request”));

* Demo shortcode
* A simple shortcode used to demonstrate the plugin.
* @see
* @param array $atts shortcode parameters
* @return string URL to demonstrate custom permalink
function my_permalink_demo_shortcode($atts) {
// default values
‘val’ => ‘lorem’
), $atts));
return sprintf(‘<a href=”%s”>My permalink</a>’,$this->my_permalink_url($val));

* Create your URL
* If the blog has a permalink structure, a permalink is returned. Otherwise
* a standard URL with param=val.
* @param sting $val Parameter to custom url
* @return string URL
function my_permalink_url($val) {
if ( get_option(‘permalink_structure’)) { // check if the blog has a permalink structure
return sprintf(“%s/my-permalink/%s”,home_url(),$val);
} else {
return sprintf(“%s/index.php?my_permalink_variable_01=%s”,home_url(),$val);

* Add your rewrite rule.
* The rewrite rules array is an associative array with permalink URLs as regular
* expressions (regex) keys, and the corresponding non-permalink-style URLs as values
* For the rule to take effect, flush the rewrite cache,
* either by re-saving permalinks in Settings->Permalinks,
* or running the my_permalink_flush_rewrite_rules() method below.
* @see
* @param object $wp_rewrite
* @return array New permalink structure
function my_permalink_rewrite_rule( $wp_rewrite ) {
$new_rules = array(
‘my-permalink/(.*)$’ => sprintf(“index.php?my_permalink_variable_01=%s”,$wp_rewrite->preg_index(1))
// a more complex permalink:
‘my-permalink/([^/]+)/([^.]+).html$’ => sprintf(“index.php?my_permalink_variable_01=%s&my_permalink_variable_02=%s”,$wp_rewrite->preg_index(1),$wp_rewrite->preg_index(2))

$wp_rewrite->rules = $new_rules + $wp_rewrite->rules;
return $wp_rewrite->rules;

* Add your custom query variables.
* To make sure that our parameter value(s) gets saved,when WordPress parse the URL,
* we have to add our variable(s) to the list of query variables WordPress
* understands (query_vars filter)
* @see
* @param array $query_vars
* @return array $query_vars with custom query variables
function my_permalink_query_vars( $query_vars ) {
$query_vars[] = ‘my_permalink_variable_01’;
// need more variables?:
$query_vars[] = ‘my_permalink_variable_02’;
$query_vars[] = ‘my_permalink_variable_03’;
return $query_vars;

* Parses a URL into a query specification
* This is where you should add your code.
* @see
* @param array $atts shortcode parameters
* @return string URL to demonstrate custom permalink
function my_permalink_parse_request($wp_query) {
if (isset($wp_query->query_vars[‘my_permalink_variable_01’])) { // same as the first custom variable in my_permalink_query_vars( $query_vars )
// add your code here, code below is for this demo

* Flushes the permalink structure.
* flush_rules is an extremely costly function in terms of performance, and
* should only be run when changing the rule.
* @see
function my_permalink_flush_rewrite_rules() {
$rules = $GLOBALS[‘wp_rewrite’]->wp_rewrite_rules();
if ( ! isset( $rules[‘my-permalink/(.*)$’] ) ) { // must be the same rule as in my_permalink_rewrite_rule($wp_rewrite)
global $wp_rewrite;
} //End Class
} //End if class exists statement

if (class_exists(‘my_permalink’)) {
$my_permalink_var = new my_permalink();

How to test the “My Permalink Demo” plugin

  • Save the code above as wp-content/plugins/ps_my_permalink.php, or get the plugin from
  • Activate the “My Permalink Demo” plugin
  • add the [mypermalink] or [mypermalink val="ipsum"] shortcode to a page or post


  • Debugging permalink errors is hard, I highly recommend Rewrite Analyzer (it helped me).



  • Thanks to Paul, the plugin now only flushes the rewrite rules when needed.


  • Fixed a bug in my_permalink_url() that gave 404 for blogs in a subdirectory


  • Initial release


Making cbnet Multi Author Comment Notification 1.1.2 WordPress multisite aware


WordPress and Pow


  1. Thanks. I’ve been meaning to look into how this works for a while now.

  2. Hei Per, Really helpful plugin. I was looking into this and felt my brain getting fried, I am really happy I stumbled onto your plugin. :-)

    I have a guestion though, maybe it´s a stupid one, but I hope you can help me. In your code for the function my_permalink_parse_request, where I can add what I want to preview. I want to preview a page witch have another shortcode tag in it witch is specified in my code. So that it previews the hole wordpress page etc.. I can´t seem to understand how to do this by the way you have coded this? Can you shed some light please?

  3. Just a little additional comment. As an example for the plugin, it would be nice to know how you would use my_permalink_parse_request to call so that it will print out the result back to the page that you have your [mypermalink] on to or another page, but the most important is that it will actually print all the template of the theme that you are currently installed. Does that make sense? Please let me know if you want me to clarify. :-)

Leave a Reply

Powered by WordPress & Theme by Anders Norén