SOLUTION
I’ve gone with Update 3 and have got it working. What I had misunderstood, was that I believed that a rewrite rule would change designers/?designer=some-designer&bid=9
to /designers/some-designer
. But it is of course the other way around.
I’ve been doing some research, but I don’t quite get how to use add_rewrite_rule().
This post is pretty close to what I need, but do I really need that much code?
My current link is this:
http://www.norwegianfashion.no/designers/?designer=Batlak-og-Selvig&bid=9
What I want is this
http://www.norwegianfashion.no/designers/Batlak-og-Selvig/
- How do I use
add_rewrite_rule()
? - I need to pass the designer ID (bid). How can I do that when using re.write rules with out it showing in the URL?
Update 1
I found this which is a bit more explainatory. But it’s not working:
function add_rewrite_rules( $wp_rewrite )
{
$new_rules = array(
'('.$template_page_name.')/designers/(.*?)/?([0-9]{1,})/?$' => 'designers.php?designer='.
$wp_rewrite->preg_index(1).'&bid='.
$wp_rewrite->preg_index(2)
);
// Always add your rules to the top, to make sure your rules have priority
$wp_rewrite->rules = $new_rules + $wp_rewrite->rules;
}
add_action('generate_rewrite_rules', 'add_rewrite_rules');
function query_vars($public_query_vars) {
$public_query_vars[] = "designer";
$public_query_vars[] = "bid";
return $public_query_vars;
}
add_filter('query_vars', 'query_vars')
Update 2
Here is another solution I’ve tried, that Jan Fabry suggesten in another thread. I put this in my functions.php, but it has no effect.
add_action('generate_rewrite_rules', 'add_rewrite_rules');
add_filter('query_vars', 'query_vars');
/* Custom re-write rules for desigenrs
------------------------------------------------------------------------------*/
function add_rewrite_rules( $wp_rewrite )
{
add_rewrite_rule('^designers/([^/]*)/([^/]*)$ /designers/?designer=$1&bid=$2 [L]', 'top');
flush_rewrite_rules(false);
}
function query_vars($public_query_vars) {
$public_query_vars[] = "designer";
$public_query_vars[] = "bid";
return $public_query_vars;
}
Update 3
I found a few examples here as well. But this is not working either 🙁
add_filter('rewrite_rules_array','wp_insertMyRewriteRules');
add_filter('query_vars','wp_insertMyRewriteQueryVars');
add_filter('init','flushRules');
// Remember to flush_rules() when adding rules
function flushRules(){
global $wp_rewrite;
$wp_rewrite->flush_rules();
}
// Adding a new rule
function wp_insertMyRewriteRules($rules)
{
$newrules = array();
$newrules['(designers)/(d*)$'] = 'index.php?pagename=designers&designer=$matches[1]';
return $newrules + $rules;
}
// Adding the bid var so that WP recognizes it
function wp_insertMyRewriteQueryVars($vars)
{
array_push($vars, 'designer');
return $vars;
}
Update 4
I also tried this solution, but still no sucess.
add_filter('search_rewrite_rules', 'designers_createRewriteRules');
function designers_createRewriteRules($rewrite) {
global $wp_rewrite;
// add rewrite tokens
$designer_token = '%designers%';
$wp_rewrite->add_rewrite_tag($designer_token, '(.+)', 'designers=');
$bid_token = '%bid%';
$wp_rewrite->add_rewrite_tag($bid_token, '(.+)', 'bid=');
$keywords_structure = $wp_rewrite->root . "designers/$designer_token/$bid_token";
$keywords_rewrite = $wp_rewrite->generate_rewrite_rules($keywords_structure);
return ( $rewrite + $keywords_rewrite );
}
Update 5
It seems that my rewrite rules are not added.
Executing the follwoing afte radding new rules: print_r($wp_rewrite)
, does not include my new rewrite rules.
Update 6
I tested Jan’s solution. But URL does not change 🙁
/* Initiation script for NF template
------------------------------------------------------------------------------*/
add_action('after_setup_theme','norwegianfashion_setup');
if ( ! function_exists( 'norwegianfashion_setup' ) ):
function norwegianfashion_setup() {
/* Here I do a lot of stuff */
// SEO friendly URL for desigenrs
add_action( 'init', 'wpa5413_init' );
add_filter( 'query_vars', 'wpa5413_query_vars' );
}
endif;
/* Custom re-write rules for desigenrs
------------------------------------------------------------------------------*/
function wpa5413_init()
{
// Remember to flush the rules once manually after you added this code!
add_rewrite_rule(
'designers/([^/]+)/?',
'index.php?pagename=designers&designer=$matches[1]',
'top' );
}
function wpa5413_query_vars( $query_vars )
{
$query_vars[] = 'designer';
return $query_vars;
}
I would really appreciate it if someone were able to help me solve this issue.
Some background on rewrite rules
The WP Rewrite system looks complicated, but in fact it’s not that hard to understand how it works. It is used to parse pretty URLs (
/designers/
) as if they were non-pretty (/index.php?pagename=designers
). The basic idea is that you have a list of rewrite rules, regular expressions that can match the incoming URLs, and rewrite them into other URLs, mostly in the form ofindex.php
with some query variables. These variables are set to parts of the regular expression that matched the URL. The rules are evaluated top to bottom, so if two rules might match, the first one “wins”.These rewrite rules are stored in the database by calling
flush_rewrite_rules()
, but because generating and writing these rules is an expensive operation, you should not do it on everyinit
. Instead, you only do it when you change the rules: probably on plugin activation (usingregister_activation_hook()
), or manually by visiting the Permalinks settings page (because it’s hard to do this automatically on theme activation). If you don’t flush the rules, callingadd_rewrite_rule()
has no effect. It is no problem to calladd_rewrite_rule()
on everyinit
, even after you flushed the rules.There are many ways to add your rewrite rules, and if you only want to add one rule, you can do this with
add_rewrite_rule()
. Because the rules for posts, pages, taxonomies, … result in multiple rules, they are created with high level functions likeadd_rewrite_tag()
,add_permastruct()
, … But these are not needed for the simple case we have here.There are also some filters, so you can also add your rules using the
generate_rewrite_rules
orgenerate_rewrite_rules_array
hooks. These give you very detailed control over the complete rules, but again,add_rewrite_rule()
is enough if you just want to add one rule.I created a little plugin that allows you to analyze the current rewrite rules, and (of course) I recommend you use it when you try to change anything.
Getting your extra info from the URL
Let’s build on the example you gave. You have the designer brand
Batlak og Selvig
, with the numberic ID (bid
)9
. You don’t want this ID in the URL, but only the name. We call the URL-friendly version of the name (without spaces or special characters) the slug:Batlak-og-Selvig
.In general, the URL should contain all info to identify the content you want to show on the page. You can use cookies or POST requests to store the actual designer ID you want to display, but this will break down if anyone shares the link, by sending it via mail, Facebook, Twitter, or just reading it out loud over the phone. If you don’t want to use the numeric ID in your URL, you should make sure the slug is unique: then you first do a lookup of the ID based on the slug, and continue as you did before.
So what we have learned now is that we want to add a rewrite rule for the pattern “
/designers/
followed by anything up to the next/
“, and save that “anything” in thedesigner_slug
query variable. In your case I believe you also want to use the page with the slugdesigners
as the general page content, so we’ll tell WordPress that too.The only thing left to do is to tell WordPress to also keep the
designer_slug
in the query variables, so you can access it later. WordPress uses a whitelist of allowed query variables, to prevent people from modifying every parameter of the posts query via the URL. Everything not on this list is ignored. Just hook into thequery_vars
hook and add your extra variable:As you can see, this answer is basically the same as my previous answer, but without the rule flushing in the code (so you can use it in your theme’s
functions.php
instead of a plugin), and with a bit more certainty and explanation because I learned a lot about rewrite rules since (and because of) answering your first question.Chat room discussion
We cleared up final issues for this question in the chat room. In the end, Steven used the
generate_rewrite_rules
hook, because theadd_rewrite_rule()
function did not seem to work for him.