• Skip to primary navigation
  • Skip to main content
  • Skip to primary sidebar

WP Realm

WordPress news, community news, reviews and more from all over the world

  • News
  • Tutorials
  • About

WordPress Rewrite Rules, Human Made Core Style!

21 January 2013 by Joe Hoyle

The WordPress rewrite system is an area many people struggle with when starting out. People not familiar with rewrite systems don’t necessarily understand what role they play and often developers who are used to using rewrite systems find WordPress’s implementation somewhat clunky.

When working on relatively complex WordPress projects, which have multiple custom taxonomies and combinations of post types, custom rewrite rules are likely to be needed.

So, what are rewrite rules? In WordPress, a rewrite rule is essentially a map of a URL pattern (using regex) to the WP_Query arguments. When the URL regex pattern is matched, the global $wp_query is populated with the arguments of the rule. For example, a year archive “page” would have a rewrite rule like:

^([d*4])/?$ => year=$matches[1]

Now, to add your own custom rewrite rules, you have hook into potentially several places. Firstly you must hook into flush_rewrite to add your regex => wp_query arguments:

add_rewrite_rule( '#some regex#', 'post_type=offer&posts_per_page=5' );

Some things to note:

  • If you want to do any more advanced wp_query args that you can not pass in the string args style, or dynamically set arguments, you will need to hook into parse_request.
  • If you have used any non-standard public query vars in your wp_query arguments you will need to hook into public_query_vars and add them to the array.
  • Then you will need to hook into template_redirect to load a custom template for that URL pattern (if you so wish).

As a large amount of the work that I do is with quite complex relationships of post types and taxonomies, I have wrapped all the rewrite and associated functionality into a simple API, called hm_add_rewrite_rule.

The function takes an array of arguments about the specific rewrite rule, though the interface is all via one function call, it is backed by a pretty modular object orientated approach. A brief rundown of the argument

<?php
regex // the regex pattern to match against the URL
query // the wp_query arguments
template // the template file to load for this rewrite, full path or relative to active theme
request_callback // callback called when the url is matched, useful for adding complex wp_query arguments
disable_canonical // if set to true, will disable the often pesky canonical redirect that can erosion sly run on complex queries
post_query_properties // list of properties to add / overwrite on the WP_Query object, useful for setting is_my_custom_page=1 style properties.
title_callback // called via the wp_title hook to easily set the page title
restrict_access // can be set to "logged_in_only" etc for private pages.
view raw args.php hosted with ❤ by GitHub

That’s about all the most useful arguments, but there are more. An example of a user profile rewrite rule:

<?php
hm_rewrite_rule( array(
'regex' => '^users/([^/]+)/?',
'query' => 'author_name=$matches[1]&',
'template' => 'user-archive.php',
'body_class_callback' => function( $classes ) {
$classes[] = 'user-archive';
$classes[] = 'user-' . get_query_var( 'author_name' );
return $classes;
},
'title_callback' => function( $title, $seperator ) {
return get_query_var( 'author_name' ) . ' ' . $seperator . ' ' . $title;
}
) );
view raw profile.php hosted with ❤ by GitHub

Another rewrite with more callback options:

<?php
hm_rewrite_rule( array(
'regex' => '^reviews/([^/]+)/?', // a review category page
'query' => 'review_category=$matches[1]&',
'template' => 'review-category.php',
'request_callback' => function( WP $wp ) {
// if the review category is "laptops" then only show items in draft
if ( $wp->query_vars['review_category'] == 'laptops' )
$wp->query_vars['post_status'] = 'draft';
},
'query_callback' => function( WP_Query $query ) {
//overwrite is_home because WordPress gets it wrong here
$query->is_home = false;
},
'body_class_callback' => function( $classes ) {
$classes[] = get_query_var( 'review_category' );
return $classes;
},
'title_callback' => function( $title, $seperator ) {
return review_category . ' ' . $seperator . ' ' . $title;
}
) );
view raw advanced.php hosted with ❤ by GitHub

Or, if you are writing a nice RESTful API, and you want to do it using WordPress rewrite rules (for the cool kids), you can define the type of method request (GET|POST|PUT|DELETE) etc, capture the post_id from the url and handle the request in the request_callback.

<?php
hm_add_rewrite_rule( array(
'request_method' => 'DELETE',
'regex' => '/api/v3/posts/([^/]+)',
'query' => 'post_id=$matches[1]',
'request_callback' => function( WP $wp ) {
wp_delete_post( $wp->query_vars['post_id'] );
exit;
}
) );
view raw api.php hosted with ❤ by GitHub

HM Rewrite is currently part of the HM Core plugin, though the hm-rewrite file is self-contained, so if you want to try hm_add_rewrite_rule() out, can can just use this file: https://github.com/humanmade/hm-core/blob/master/hm-core.rewrite.php.

Remember: Whenever you add a new rewrite rule via hm_add_rewrite_rule() or update the regex/query of an existing rule, you have to flush your permalinks (just visit the permalinks options page).

ShareTweet

Filed Under: Practical

Primary Sidebar

Recent Comments

  • Remkus de Vries on Building a Multilingual Website? These are the Questions to Ask.
  • Tuba on Building a Multilingual Website? These are the Questions to Ask.
  • WPML, qTranslate eller Polylang: hvilken du skal velge og hvorfor? (2020) - My Blog on Building a Multilingual Website? These are the Questions to Ask.
  • Marian Malahin on Building a Multilingual Website? These are the Questions to Ask.
  • WPML,qTranslate X或Polylang – 三种最流行的多语言WordPress插件比较(2019) – wordpress on Building a Multilingual Website? These are the Questions to Ask.
Copyright © 2012 – Today – WP Realm