0

I tried to fix my problem by using wordpress rewrite rules but sadly it took me so long I tried this approach. I got it working for one of my simpler problems but now I can't get it to work for my two variable rewrite.

# START Custom rules.
RewriteEngine On

RewriteRule ^examentraining/vak/([^/]+)/([^/]+)/?$ index.php?p=1316&vakname=$1&level=$2 [L]
RewriteRule ^examentraining/training/([^/]+)/?$ index.php?pagename=examentraining/training&trainingid=$1 [L]

# FIN customrules

# 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

The second rule rewrites index.php?pagename=examentraining/training$trainingid=VAKID => /examentraining/training/VAKID/. This one works and has been tested.

I would like my first example to also work, this one needs to rewrite /index.php?p=1316&vakname=VAKNAME&level=LEVELNAME => /examentraining/vak/VAKNAME/LEVELNAME/.

LEVELNAME and VAKNAME are both strings that should be able to contain A-Z,a-z,_,&. I have tested this rewrite rule on multiple online tester but when I use it with wordpress it keeps failing.

I enabled logging for .htaccess and I can see that the rewrite is functioning correctly but I can't follow it afterwards.

The log: https://gist.github.com/ITWarrior/9292036

I hope somebody can help me, I have to get this done and I have tried al sorts of ways.

EDIT 1

I added remove_filter('template_redirect', 'redirect_canonical'); to my plugin. Now requesting /examentraining/vak/natuurkunde/vwo gets me to /examentraining/vak/natuurkunde/vwo but with an 404 not found wordpress error. The log of this request: https://gist.github.com/ITWarrior/9294435 The rewrite works fine and entering the url after the first rewrite actually gets me to the correct page (/index.php?p=1316&vakname=aardrijkskunde&level=vwo).

2
  • 1
    Did you disable the redirect_canonical code in WordPress?
    – Otto
    Mar 1, 2014 at 16:25
  • @Otto I just disabled the edirect_canonical and I think it has brought me a closer to the solution. When I entered the url /examentraining/vak/natuurkunde/vwo I used to end up on /examentraining/vak/ and now I get to /examentraining/vak/natuurkunde/vwo/ which returns an 404 not found. Mar 1, 2014 at 18:11

1 Answer 1

0

After weeks of fiddling around and trying all sorts of tricks, I finally figured it out. There we're two things I was doing wrong, I wanted wordpress to be able to access get last two value's in between slashes as GET parameters when an url like this /examentraining/vak/VAKNAME/LEVELNAME/ is submitted to Wordpress. p=1316&vakname=VAKNAME&level=LEVELNAME => /examentraining/vak/VAKNAME/LEVELNAME/ is incorrect because it worked the other way around. But when I reversed the rewrite rule it still didn't work.

I still have to figure out the exact reason but I never managed to get it working via the .htaccess file. Then I came across the following class by Kyle E Gentile.

<?php
/*
//Author Kyle E Gentile
//To use this class you must first include the file.  
//After including the file, you need to create an options array.  For example:
$options = array(
    'query_vars' => array('var1', 'var2'),
    'rules' => array('(.+?)/(.+?)/(.+?)/?$' => 'index.php?pagename=$matches[1]&var1=$matches[2]&var2=$matches[3]')
);
//After creating our $option array, 
//we will need to create a new instance of the class as below:
$rewrite = new Add_rewrite_rules($options);
//You must pass the options array, this way. (If you don't there could be problems) 
//Then you can call the filters and action functions as below:
add_action('wp_head', array(&$rewrite, 'flush_rules'));
add_action( 'generate_rewrite_rules', array(&$rewrite, 'add_rewrite_rules') );
add_filter( 'query_vars', array(&$rewrite, 'add_query_vars') );
//That is it.
*/

//prevent duplicate loading of the class if you are using this in multiply plugins
if(!class_exists('add_rewrite_rules')){

    class Add_rewrite_rules{

        var $query_vars;
        var $rules;

        function __construct($options){
            $this->init($options);
        }

        function init($options){
            foreach($options as $key => $value){
                $this->$key = $value;
            }
        }

        function rules_exist(){
            global $wp_rewrite;

            $has_rules = TRUE;

            foreach($this->rules as $key => $value){
                if(!in_array($value, $wp_rewrite->rules)){
                    $has_rules = FALSE;
                }   
            }

            return $has_rules;
        }

        //to be used add_action with the hook 'wp_head'
        //flushing rewrite rules is labor intense so we better test to see if our rules exist first
        //if the rules don't exist flush its like after a night of drinking  
        function flush_rules(){
            global $wp_rewrite;

            if(!$this->rules_exist()){
                //echo "flushed"; // If want to see this in action uncomment this line and remove this text and you will see it flushed before your eyes
                $wp_rewrite->flush_rules();
            }
        }

        //filter function to be used with add_filter() with the hook "query_vars"
        function add_query_vars($query_vars){

            foreach($this->query_vars as $var){
                $query_vars[] = $var;
            }

            return $query_vars;
        }

        //to be used with a the add_action() with the hook "generate_rewrite_rules"
        function add_rewrite_rules(){
            global $wp_rewrite;

            $wp_rewrite->rules = $this->rules + $wp_rewrite->rules;
        }

    }

}
?>

I added the following function to the init of my plugin.

public function rewriteRules()
{
//Add the query variables to the list so wordpress doesn't discard them or worse use them to try and find by itself what page to serve.
    $options = array(
        'query_vars' => array('trainingid', 'vakname'),
        'rules' =>
            array( 'uncategorized/vak/([^/]+)/([^/]+)/?$' => 'index.php?p=1316&vakname=$matches[1]&level=$matches[2]'
            )
    );

    //I use a autoloader but if you don't you have to include the class.
    //include_once('path/to/AddRewriteRules.php');
    $rewrite = new AddRewriteRules($options);
    add_action('wp_head', array(&$rewrite, 'flush_rules'));
    add_action('generate_rewrite_rules', array(&$rewrite, 'add_rewrite_rules'));
    add_filter('query_vars', array(&$rewrite, 'add_query_vars'));


}

This solved the problem but there was a step before this, as you might have noticed I wanted to match examentraining/vak/VAKNAME/LEVELNAME/ but I ended up matching uncategorized/vak/VAKNAME/LEVELNAME/. This is because for some reason either Wordpress SEO or Wordpress itself messes with my request. To find the correct request URL use the amazing debug bar plugin. It tells you exactly what request is coming in and what rules have been matched.

I hope this helps anybody!

Your Answer

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

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