WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I have build a plugin where I can output special php pages on a page using shortcode.

The plugin directory consists of the following php pages.


The shortcode function which is on core.php is as follows,

function output_store(){
function filter($content = '') {
    if ( '' == $content || !strstr($content, '[WP_online_store]') ) { return $content; }
    return preg_replace('|(<p>)?(\n)*[(\[)WP_online_store(\])](\n)*(</p>)?|', do_shortcode( '[WP_online_store]' ), $content);
add_shortcode('output_store', 'output_store');
add_filter('the_content', 'filter');

[output_store] will be placed on any page for example on store page so when I visit the store page the default content of that page will display the index.php file from the plugin directory.

In the index.php file I have links for accessing login.php, product_info.php, account.php and checkout.php each has url of:

login.php => http://website.com/store/?slug=login.php
product_info.php => http://website.com/store/?slug=product.info.php
account.php => http://website.com/store/?slug=account.php
checkout.php => http://website.com/store/?slug=checkout.php

Also on index.php I have products there pulled from mysql database in which accessible by links like http://website.com/store/?slug=product_info.php&products_id=38 and so on.

Now I wanted to rewrite these urls to be search engine friendly. I wanted:

http://website.com/store/?slug=login.php to become http://website.com/store/login
http://website.com/store/?slug=account.php to become http://website.com/store/account
http://website.com/store/?slug=checkout.php to become http://website.com/store/checkout

and all product urls:

    like http://website.com/store/?slug=product_info.php&products_id=38 
    to become http://website.com/store/product-info/38

How can I accomplish that using wordpress's WP Rewrite?

I tried this for the product info pages:

// Define permalinks
function add_query_vars($aVars) {
$aVars[] = "products_id";
return $aVars;

function add_rewrite_rules($aRules) {
$aNewRules = array('product-info/([^/]+)/?$' => 'index.php?slug=product_info.php&products_id=$matches[1]');
$aRules = $aNewRules + $aRules;
return $aRules;

add_filter('query_vars', 'add_query_vars');
add_filter('rewrite_rules_array', 'add_rewrite_rules');

function isset_productinfo() {
  if(isset($wp_query->query_vars['products_id'])) {
   $sMsdsCat = urldecode($wp_query->query_vars['products_id']);

// End Special Permalinks

Flushed my permalinks and its not working.. When I access http://website.com/store/product-info/38 and goes on http://website.com/store/ instead of displaying the product page. How can I fix this? or do you have any other solutions?

Please help..

share|improve this question

In your case would be something like:

add_action('rewrite_rules_array', 'rewrite_rules');
function rewrite_rules($rules) {
    $new_rules = array(
        'product/([0-9]+)/?$' => 'index.php?product=$matches[1]'
    return $rules + $new_rules;

add_action('query_vars', 'add_query_vars');
function add_query_vars($vars) {
    array_push($vars, 'product');
    return $vars;

add_action('template_redirect', 'custom_template_redirect');
function custom_template_redirect() {
    global $wp_query, $post;
    if (get_query_var('product')) {
        include(YOURPLUGINDIR . 'templates/product_template.php');

In product_template.php, you can access which product was queried with get_query_var('product').

After modifying the rules array you need to flush the rules. Do this by simply visiting the permalink admin page on http://yoursite/wp-admin/options-permalink.php.

Also, you can see the rules testing order and which one is being matched with:

add_action('wp', 'debug_rules');
function debug_rules() {
    global $wp, $wp_query, $wp_rewrite;
    echo $wp->matched_rule . ' | ' . $wp_rewrite->rules[$wp->matched_rule];

And please, try to make your plugin work for both cases (GET variables and custom rewrite rules), as you never know if your users will be able to run permalinks.

So, as the docs tell us:

if ( get_option('permalink_structure') ) {
    /* do everything as above */
} else {
    /* so stuff only with GET variables
share|improve this answer
Flushing WP Rewrite on on wp_loaded is a bad idea. It refreshes the rules on every page load which is unnecessary. Much better to use the plugin activation hook. – KalenGi Jul 27 '12 at 4:46
But products are loaded via GET variables.. like /?slug=product_info.php&products_id=38 but on your code, it seems that when there is product get variable it will only redirect to /?slug=product_info.php – Ken Jul 27 '12 at 13:51
@KalenGi see the edit. – vmassuchetto Nov 23 '14 at 20:38
@Ken, get_query_var( 'product' ) should work both with permalink structures or GET requests. – vmassuchetto Nov 23 '14 at 20:40

I think the issue in this case is a mismatch in the query arg name:

In your requirement you have:


In your implementation you have:

$aNewRules = array('product-info/([^/]+)/?$' => 'index.php?slug=product_info.php&products_id=$matches[1]');

Now if the code in product_info.php expects product_id then products_id won't work.

share|improve this answer
Sorry.. Its a typo error.. It is originally products_id.. – Ken Jul 27 '12 at 5:44

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

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