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..

2 Answers 2


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
  • 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, 2012 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, 2012 at 13:51
  • @KalenGi see the edit. Nov 23, 2014 at 20:38
  • @Ken, get_query_var( 'product' ) should work both with permalink structures or GET requests. Nov 23, 2014 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.

  • Sorry.. Its a typo error.. It is originally products_id..
    – Ken
    Jul 27, 2012 at 5:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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