Adding custom rewrite rules to WordPress - wordpress

My WordPress site has a portfolio that is at www.mysite.com/portfolio/. The portfolio sections and items are administered through a custom plugin I created. I want to access the individual items like www.mysite.com/portfolio/my-cool-photo and have that put "my-cool-photo" into a query string like ?portfolio_item=my-cool-photo so I can read it from my code.
In the plugins activation PHP file I have this code:
function add_rewrite_rules($wp_rewrite) {
$new_rules = array(
'portfolio/(.+)/?$' => 'index.php?&portfolio_item=$1'
);
$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[] = "portfolio_item";
return $public_query_vars;
}
add_filter('query_vars', 'query_vars');
This adds the rewrite rule to the array OK. The problem is it's not doing anything. When I go to www.mysite.com/portfolio/testing/ I get the "This is somewhat embarrassing, isn’t it?" WordPress 404 error page. Obviously the redirect isn't working, so the query string won't be filled, but just to make sure I did this:
global $wp_query, $wp_rewrite;
if ($wp_rewrite->using_permalinks()) {
$searchKey = $wp_query->query_vars['portfolio_item'];
} else {
$searchKey = $_GET['portfolio_item'];
}
...and sure enough the query string isn't getting passed.
Is there something I'm missing?

After you update the WordPress rewrite rules, you need to flush them:
http://codex.wordpress.org/Function_Reference/flush_rewrite_rules
You can choose to flush with the $hard parameter true, and then you should be able to see your rewrite rules in the .htaccess file.

Here is the example rewriting url code. Hopefully this will help users.
In this url like http://www.domainname.com/test-page?urltags=ABCD is run as http://www.domainname.com/test-page/ABCD
<?php
function add_my_rule() {
global $wp;
$wp->add_query_var('tags');
add_rewrite_rule('test-page/([^/]*)','index.php?pagename=test-page&urltags=$matches[1]','top');
}
function add_my_tags() {
add_rewrite_tag('%urltags%', '([^&]+)');
}
add_action('init', 'add_my_rule');
add_action('init', 'add_my_tags', 10, 0);
?>

Related

Wordpress custom rewrite rules not working

I want to add a simple custom Wordpress rewrite rule but somehow I don't get this working.
This URL
http://www.gewerbesteuer.de/steuer/muenchen
should call this
http://www.gewerbesteuer.de/index.php?pagename=gewerbesteuerhebesaetze&loc=muenchen.
So I want to call a page, which displays tax rates for a certain city, the city should be in the url as the last part.
Here is my code:
function custom_rewrite_tag() {
global $wp_rewrite;
add_rewrite_tag('%loc%', '([^&]+)');
add_rewrite_rule('steuer/([^/]+)',
'index.php?pagename=gewerbesteuerhebesaetze&loc=$matches[1]', 'top');
flush_rewrite_rules();
}
function query_vars($query_vars ) {
$query_vars[] = 'loc';
return $query_vars;
}
add_action('init', 'custom_rewrite_tag');
add_filter( 'query_vars', 'query_vars' );
The rewrite rule is working but the parameter (in this case loc) is not picked up. Even if I hardcode the rewrite rule with a certain city like
add_rewrite_rule('steuer/([^/]+)',
'index.php?pagename=gewerbesteuerhebesaetze&loc=muenchen', 'top');
it still doesen't pick up the value of the loc parameter. I also noticed that the $matches array is empty and doesn't contain any values.
I went through all the docs at wordpress and the questions here, but couldn't find the problem. Any ideas?
Thanks
Bernhard
Can you try adding this and see if this makes any difference?
Edited
I have changed the paramter in the rewrite rule from "pagename" to "page_id" - I am assuming its 2207 as thats what it said from looking at the body class on your website's page.
I also removed flush_rewrite_rules() from the custom_rewrite_rules_tags function, can you try this now then go to Options > Permalinks and re-save again.
function custom_rewrite_rules_tags() {
global $wp_rewrite;
add_rewrite_tag('%loc%', '([^&]+)');
add_rewrite_rule(
'steuer/([^/]+)',
'index.php?page_id=2207&loc=$matches[1]',
'top'
);
}
add_action('init', 'custom_rewrite_rules_tags');
function custom_query_vars($query_vars ) {
$query_vars[] = 'loc';
return $query_vars;
}
add_filter( 'query_vars', 'custom_query_vars' );

Wordpress rewrite add base prefix to pages only

I have a problem I've encountered when trying to finish a project.
I have the current permalink structure set as /%postname%/
I made my own function on giving a prefix to posts only so my posts are rewritten as /{prefix}/%postname%/.
My problem is that I want to change the permalink of the pages as I did with the posts so my pages will have a prefix like /{prefix}/%pagename%/.
What I tried and didn't work:
Re-declare the PAGES post type and set a rewrite slug.
Tried adding a custom rewrite rule as a function but it didn't work:
$rewrite_rules += array('mycustomprefix/(.+?)/([0-9]+)/([^/]+)/([^/]+)/?$' =>'index.php?pagename=$matches[1]',
Is this possible? Are there any developers out there who encountered the same issue?
For anybody interested, I've fixed my issue in the following manner:
function change_author_permalinks() {
global $wp_rewrite;
// Change the value of the author permalink base to whatever you want here
$wp_rewrite->author_base = '';
// Change the value of the page permalink base to whatever you want here
$wp_rewrite->page_structure = 'static/%pagename%';
$wp_rewrite->flush_rules();
}
add_action('init','change_author_permalinks');
Hope this helps others as I couldn't find any help for this anywhere. For morer information on what you can change this way, check out http://codex.wordpress.org/Class_Reference/WP_Rewrite
Have you updated the permalinks structure after adding this rewrite to your functions.php ? It works for me :)
add_filter( 'page_rewrite_rules', 'customprefix_page_rewrite_rules' );
function customprefix_page_rewrite_rules( $rewrite_rules )
{
end( $rewrite_rules );
$last_pattern = key( $rewrite_rules );
$last_replacement = array_pop( $rewrite_rules );
$rewrite_rules += array(
'mycustomprefix/(.+?)/?$' => 'index.php?pagename=$matches[1]',
$last_pattern => $last_replacement,
);
return $rewrite_rules;
}
I found this solution working for me better... and it's also much cleaner code.
add_action( 'init', 'custom_page_rules' );
function custom_page_rules() {
global $wp_rewrite;
$wp_rewrite->page_structure = $wp_rewrite->root . 'your-page-prefix/%pagename%';
}
I found the code here: http://wpforce.com/change-wordpress-page-permalinks/

How to make Wordpress permalinks ignore custom url rewrite

i'm currently working on a wordpress site that needs to have the option to be offered in french. i've found a way to make the theme work with the fr_FR po and mo files when i add a querystring variable l. i.e.
site.tld will yield the vanilla english site, while site.tld/?l=fr will activate the following code in my functions.php to serve the french translation:
<?php
// http://codex.wordpress.org/Plugin_API/Filter_Reference/locale
add_filter( 'locale', 'set_my_locale' );
function set_my_locale( $lang ) {
if ("fr" == substr(strtolower(trim(strip_tags(stripslashes($_GET['l'])))), 0, 2)) {
// set language to french
return "fr_FR";
} else {
// return original locale
return $lang;
}
}
?>
this setup is already working. my question is: how do i rewrite the url so instead of site.tld/?l=fr i can just prepend the folder structure with fr i.e. site.tld/fr/?
so like if there's a page site.tld/portoflio/autumn/ in english, site.tld/fr/portfolio/autumn/ will spit out the french one. i got this idea from the apple website, where the language is always prepended to the folder structure.
i can already make this happen with an external redirect in htaccess:
RewriteBase /
RewriteCond ^[a-z]{2}/
RewriteRule ^([a-z]{2})/(.*)$ /$2?l=$1 [R,L]
this works, but once i remove the R flag it serves the french-translated 404 not found isntead. i'm guessing what i did is messing-up with wordpress' rewrite rules because i need to use pretty permalinks. right now i'm set to use Month and name (/%year%/%monthnum%/%postname%/) in the admin general options.
my question is, how do i make wordpress ignore the /fr/ part and still serve the correct page/post/etc?
is this even possible? am i on the right track here? i need your help especially doing what's WISE and not just what's NICE. i tried this http://pmg.co/a-mostly-complete-guide-to-the-wordpress-rewrite-api but for the life of me i can't make it work. :/
UPDATE: ok, so here's some progress taking cue from #relu below:
i made sure my rules were canned from .htaccess
i then added the rules from #relu but in the following way, because Relu's always sent me to the same address without the /fr:
<?
// http://pmg.co/custom-wordpress-shortlinks
add_action( 'init', 'pmgtut_add_rewrites' );
function pmgtut_add_rewrites() {
add_rewrite_rule( '^([a-z]{2})/?$', 'index.php?l=$matches[1]', 'top' );
add_rewrite_rule( '^([a-z]{2})/(.*)$', 'index.php?l=$matches[1]&q=$matches[2]', 'top' );
}
add_filter( 'query_vars', 'pmgtut_query_vars', 10, 1 );
function pmgtut_query_vars( $vars ) {
$vars[] = 'l';
return $vars;
}
?>
now the /fr stays in the address bar, so that's a good thing, but two problems persist:
wordpress is serving me the main index page. seems like it's not using the &q=$matches[2] part of the rule; and
the locale still doesn't get set properly. i checked if the variable l is getting fed, so i added echo 'l: $l'; after $l = get_query_var('l'); and interestingly i get two echoes: one l: and another l: fr right after that. is the locale filter being run twice? seems like the first time it doesn't see the value of the queryvar, and then there seems to be a second time that it outputs l: with fr already in there.. at the end of the day the locale still doesn't get changed.
aaaah help.
FINAL UPDATE: in my last breath of frustration i searched again, and found this plugin qtranslate. does what i need. thanks y'all, esp to #relu's epic effort and stayin pow'r.
Add this to your functions.php
add_filter( 'rewrite_rules_array','my_insert_rewrite_rules' );
add_filter( 'query_vars','my_insert_query_vars' );
add_action( 'wp_loaded','my_flush_rules' );
// flush_rules() if our rules are not yet included
function my_flush_rules(){
$rules = get_option( 'rewrite_rules' );
if ( ! isset( $rules['^([a-z]{2})/(.*)$'] ) ) {
global $wp_rewrite;
$wp_rewrite->flush_rules();
}
}
// Adding a new rule
function my_insert_rewrite_rules( $rules )
{
$newrules = array();
$newrules['^([a-z]{2})/(.*)$'] = 'index.php?l=$matches[1]&q=$matches[2]';
return $newrules + $rules;
}
// Adding the l var so that WP recognizes it
function my_insert_query_vars( $vars )
{
array_push($vars, 'l');
return $vars;
}
Haven't tested this, it may need some tweaking, but this is the way to do it.
I've basically adapted the version found here.
It also registers the "l" query var so you can get it's value by calling: get_query_var
add_filter( 'locale', 'set_my_locale' );
function set_my_locale( $lang ) {
$l = get_query_var('l');
if ("fr" == $l) {
// set language to french
return "fr_FR";
} else {
// return original locale
return $lang;
}
}
UDATE: Ignore the above!
Remove the my_insert_query_vars() filter and replace it with:
function register_rewrite_tag() {
add_rewrite_tag('%l%', '([a-z]{2})');
}
add_action('init', 'register_rewrite_tag');
Here are also the updated rewrites for pages and posts, I've looked at WordPress' $wp_rewrite->rules and adapted them to fit this special case:
function pmgtut_add_rewrites() {
add_rewrite_rule( '^([a-z]{2})/?$', 'index.php?l=$matches[1]', 'top' );
add_rewrite_rule( '^([a-z]{2})/(.?.+?)(/[0-9]+)?/?$', 'index.php?l=$matches[1]&pagename=$matches[2]&page=$matches[3]', 'top' ); // Pages
add_rewrite_rule( '^([a-z]{2})/([^/]+)(/[0-9]+)?/?$', 'index.php?l=$matches[1]&name=$matches[2]&page=$matches[3]', 'top' ); // Posts
}
maybe out of topic but here's another rewrite rule for languages of the form; en_us/ or jp/
add_rewrite_rule( '^([a-z]{2}_[A-Z]{2}|^[a-z]{2})/?$', 'index.php?l=$matches[1]', 'top' );

Custom rewrite rules in Wordpress

I'm in trouble with the internal wordpress rewrite rules.
I've read this thread but I still can't get any results: wp_rewrite in a WordPress Plugin
I explain my situation:
1) I have a page_template called 'myplugin_template.php' associated to a wordpress page called "mypage".
<?php
get_header();
switch ($_GET['action']) {
case = "show" {
echo $_GET['say'];
}
}
get_footer();
?>
2) I need to create a rewrite rule for this link:
http://myblog/index.php?pagename=mypage&action=show&say=hello_world
If I use this url all the things works without problems but I'd like to achieve this result:
http://myblog/mypage/say/hello_world/
I really don't want to hack my .htaccess file but I don't know how I can do this with the internal wordpress rewriter.
You'll need to add your own rewrite rule and query vars - pop this in functions.php;
function my_rewrite_rules($rules)
{
global $wp_rewrite;
// the slug of the page to handle these rules
$my_page = 'mypage';
// the key is a regular expression
// the value maps matches into a query string
$my_rule = array(
'mypage/(.+)/(.+)/?' => 'index.php?pagename=' . $my_page . '&my_action=$matches[1]&my_show=$matches[2]'
);
return array_merge($my_rule, $rules);
}
add_filter('page_rewrite_rules', 'my_rewrite_rules');
function my_query_vars($vars)
{
// these values should match those in the rewrite rule query string above
// I recommend using something more unique than 'action' and 'show', as you
// could collide with other plugins or WordPress core
$my_vars = array(
'my_action',
'my_show'
);
return array_merge($my_vars, $vars);
}
add_filter('query_vars', 'my_query_vars');
Now in your page template, replace $_GET[$var] with get_query_var($var) like so;
<?php
get_header();
switch (get_query_var('my_action')) {
case = "show" {
echo esc_html(get_query_var('my_say')); // escape!
}
}
get_footer();
?>

Date-based archives for custom post_types (wordpress 3.0)

If I have a custom post type named 'my_type', how can I get Wordpress to make date-based archives, for example:
mysite.com/my_type/2010/
mysite.com/my_type/2010/07/
mysite.com/my_type/2010/07/28/
I'm looking for tips both on creating the rewrite rules and on linking the urls to templates.
Thanks!
Update:
I've tried the following in my functions.php (EVENT_TYPE_SLUG is a constant defined elsewhere):
function event_rewrite_rules() {
global $wp_rewrite;
$new_rules = array(
EVENT_TYPE_SLUG."/([0-9]{4})/([0-9]{1,2})/$" => 'index.php?post_type=event&year='.$wp_rewrite->preg_index(1).'&monthnum='.$wp_rewrite->preg_index(2),
EVENT_TYPE_SLUG."/([0-9]{4})/$" => 'index.php?post_type=event&year='.$wp_rewrite->preg_index(1),
);
$wp_rewrite->rules = $new_rules + $wp_rewrite->rules;
}
add_action('generate_rewrite_rules', 'event_rewrite_rules');
the rewrite rules show up in $wp_rewrite-> rules, but when I navigate to those pages I get a 404 error. If I manually navigate to mysite.com/index.php?post_type=event&year=2010, I get redirected to mysite.com/2010?post_type=event
Benj I think WordPress automatically creates archives for custom post type
OK ... took some time but I figured this out (there may be more elegant solutions out there).
1) Create a standard wordpress page to serve as the archive page (and to give me access to the template). I defined the page's slug as a constant (EVENT_ARCHIVE_BASE) so that it's just hard-coded in one place and referenced everywhere else.
2) Make custom rewrite rules that catch that page's urls and redirect them to the page:
function event_date_queryvars($qvars) {
array_push($qvars, 'eyear', 'emonth');
return $qvars;
}
add_filter('query_vars', 'event_date_queryvars');
function event_date_rewrite_rules() {
// Adds rewrite rules for date-based event archives
global $wp_rewrite;
$new_rules = array(
EVENT_ARCHIVE_BASE."/([0-9]{4})/([0-9]{1,2})/?$" =>
"index.php?pagename=".EVENT_ARCHIVE_BASE."&eyear=".$wp_rewrite->preg_index(1)."&emonth=".$wp_rewrite->preg_index(2),
EVENT_ARCHIVE_BASE."/([0-9]{4})/?$" => "index.php?pagename=".EVENT_ARCHIVE_BASE."&eyear=".$wp_rewrite->preg_index(1),
);
$wp_rewrite->rules = $new_rules + $wp_rewrite->rules;
}
add_action('generate_rewrite_rules', 'event_date_rewrite_rules');
3) At the top of my page template, I check for the custom query vars and build the page accordingly. (I should have been able to use the built-in year and monthnum, but couldn't get them to work properly. Future troubleshooting):
// Was the page called with a specific year, month, or just plain?
$year = get_query_var('eyear');
$monthnum = sprintf('%02d', get_query_var('emonth'));
if ($monthnum) {
$list_type = 'Month';
$monthname = $month[$monthnum];
$heading = "Events from $monthname, $year";
} elseif ($year) {
$list_type = 'Year';
$heading = "Events from $year";
} else {
$list_type = 'AllPast';
$heading = get_the_title();
}
Thanks for the help, and hope this is useful for someone else! Let me know if you have a simpler/built-in way to do this.
I managed to find a more elegant/built-in solution.
The trick is in the "post_type=article" parameter.
If you create a rewrite like so:
'(articles)/([0-9]{4})' => 'index.php?post_type=article&eyear=' . $wp_rewrite->preg_index(2)
This will then keep your URL structure, but go through the default 'archive' template.
Then you steal the template away from the default to your own archive template. (for instance 'archive-articles.php')
This function accomplishes this (works for me):
add_action("template_redirect", 'my_template_redirect');
// Template selection
function my_template_redirect()
{
global $wp;
global $wp_query;
if ($wp->query_vars["post_type"] == "article")
{
if (have_posts())
{
include(TEMPLATEPATH . '/archive-articles.php');
die();
}
else
{
$wp_query->is_404 = true;
}
}
}
You'll still need to create your own methods to handle the get_query_var()'s for the year/month/day, but at least you don't need to create a custom page template.

Resources