Rewriting URLs in WordPress: Tips and Plugins

The newest updates to WordPress have allowed for developers to customize their personal website very quickly. It’s simple to update areas of your theme, replace widgets in the sidebar, and even write your own custom PHP code functions. The expanse is huge – and one area of popularity is rewriting pretty URL permalinks.



(Image Source)

There are a few methods you can use to go about updating the default WordPress rewrite system. In this tutorial I will share a few examples and demonstrate how simple the process can be. You will need some understanding of PHP to follow what’s going on in the code, but it’s so easy to copy and paste into your own template, there’s practically no work involved.

Understanding WP_Rewrite

If you are at all familiar with mod_rewrite on Apache servers then you’ll pick up on the WordPress rewrite syntax. Their system is still built on top of an .htaccess file, but all the rules are coded in PHP. This actually makes the process a bit easier since we have more control over writing our own URLs.

I recommend skimming the $wp_rewrite class page as it has tons of info on the subject. There are even small examples we can reference to make everything easier to understand. Most of the code can be written directly into your theme’s functions.php file. Let’s start by looking at the default rewrites already included with WordPress.

Content of $wp_rewrite->rules

By declaring the $wp_rewrite class as global we have access to all of the internal data. When you go to append your own rules these are added into an array with the name $wp_rewrite->rules. It’s important to remember this variable since you’ll likely need to reference the data many times during development.

<div><code>  <?php  global $wp_rewrite;  print_r($wp_rewrite->rules);  ?>  </code></div>  

I added this block of code into my theme’s page.php file. It will output a large array of data which looks like a big mess. But if you View Source on your page it’s actually easy to see which rewrite rules are matched to which filename. For example, let’s look at the rules for category rewrites:

[category/(.+?)/?$] => index.php?category_name=$matches[1]  

The bit on the left side in brackets is our Apache RewriteRule to look for. Starting with the section /category/ followed by any string of characters. If this is matched then the server knows to reference index.php?category_name= while replacing the variable on the end.

Setting Custom Permalinks

There is so much content to go over in the $wp_rewrite class alone. Many other properties can be referenced, such as $wp_rewrite->category_base or $wp_rewrite->author_base for pulling the default URL structures for these pages. But aside from pulling WP’s default settings we can also build our own rules.

Rebuilding the Author Base

When you enter the Permalinks settings page you have the option of resetting category and tags bases. However the option to reset your author base is strangely missing.

But we can use the add_rewrite_rule() from WordPress’ codex to integrate some new settings. In this case I’ve replaced /author/ with /writer/ but you could use whatever base you like. Additionally I’ve copied some of the other redirects for author pages and RSS feeds. You can add this block of code into your theme’s functions.php file.

add_action( 'init', 'add_author_rules' );  function add_author_rules() {       add_rewrite_rule(          "writer/([^/]+)/?",          "index.php?author_name=$matches[1]",          "top");  	      add_rewrite_rule(  	"writer/([^/]+)/page/?([0-9]{1,})/?",  	"index.php?author_name=$matches[1]&paged=$matches[2]",  	"top");  	      add_rewrite_rule(  	"writer/([^/]+)/(feed|rdf|rss|rss2|atom)/?",  	"index.php?author_name=$matches[1]&feed=$matches[2]",  	"top");  		      add_rewrite_rule(  	"writer/([^/]+)/feed/(feed|rdf|rss|rss2|atom)/?",  	"index.php?author_name=$matches[1]&feed=$matches[2]",  	"top");  }  

This function can be accessed even without using the $wp_rewrite variable. Some developers like this method because it’s simpler than hard-coding with class properties. However I’ve also noticed this method is not always reliable for some WordPress installations. There is actually a second option to add these rules on the hook after flushing your .htaccess (see below).

Author Base using generate_rewrite_rules

Writing for this method we will again need the global $wp_rewrite class. I’ve then setup a new variable named $new_rules which contains an associative array of data. My example code below just rewrites for the basic author page section.

function generate_author_rewrite_rules() {    global $wp_rewrite;    $new_rules = array(      "writer/([^/]+)/?" => "index.php?author_name=".$wp_rewrite->preg_index(1)    );    $wp_rewrite->rules = $new_rules + $wp_rewrite->rules;  }  

But if we want to include multiple pages and RSS feeds we can beef up the array. You have the option of creating a PHP function to push associative array data which may be a bit too complex. We could also split the data blocks via commas, behaving as separate entities in the array. Check out my updated code again written in functions.php theme file.

function generate_author_rewrite_rules() {    global $wp_rewrite;    $new_rules = array(      "writer/([^/]+)/?" => "index.php?author_name=".$wp_rewrite->preg_index(1),  	"writer/([^/]+)/page/?([0-9]{1,})/?" => "index.php?author_name=".$wp_rewrite->preg_index(1)."&paged=".$wp_rewrite->preg_index(2),  	"writer/([^/]+)/(feed|rdf|rss|rss2|atom)/?" => "index.php?author_name=".$wp_rewrite->preg_index(1)."&feed=".$wp_rewrite->preg_index(2),  	"writer/([^/]+)/feed/(feed|rdf|rss|rss2|atom)/?" => "index.php?author_name=".$wp_rewrite->preg_index(1)."&feed=".$wp_rewrite->preg_index(2)    );    $wp_rewrite->rules = $new_rules + $wp_rewrite->rules;  }  

Just remember that neither of these methods will work until after you’ve flushed the original rewrite rules. You will have to do this any time you make changes to these functions, but afterwards your new rules will stick indefinitely.

Flushing the Rewrite Rules

Whenever you make an update to the URL rewrite code, the changes are not applied immediately. You have to flush the .htaccess rewrite rules so your new code will be added. However performing this on every page init is extremely wasteful as it writes to the database and hard-refreshes the .htaccess file.

A better method is to access your permalinks page in the admin panel and re-save the changes. This always calls a flush_rewrite_rules so you never have to worry about users on the frontend experiencing loading troubles. And it only takes one time to re-save the page and update all the rules in your system. But if this doesn’t work you can try calling $wp_rewrite->flush_rules();

Using non-WP Rules

Inside the $wp_rewrite class we have access to dozens of properties. One of the more significant options is $wp_rewrite->non_wp_rules which collects an array of redirects which do not hit the index.php file.

This is actually used most often in WordPress plugin development. You can push a specific custom URL type (such as /calendar/june-2012/) into the backend of your website(/wp-content/plugins/calendarplug/myscript.php). But of course there are further uses for this associative array of custom rewrite rules other than plugins. I’ve provided an excellent example in the context below.

Masking your Theme Files

This is a common suggestion I see frequently on WordPress discussion boards. Ideally we’d like to reference some files inside the /wp-content/themes/mytheme/ folder with a more elegant URL. Notice that this will require a different set of WordPress rewrites to change the directory structure.

WordPress’ internal rewrite system always pushes content towards a single routing file. In the default case, we use index.php along with any extra query string data. But for hiding our standard template directory(/wp-content/themes/mytheme/*) we will need to display many different files.

add_action('generate_rewrite_rules', 'themes_dir_add_rewrites');    function themes_dir_add_rewrites() {    $theme_name = next(explode('/themes/', get_stylesheet_directory()));      global $wp_rewrite;    $new_non_wp_rules = array(      'css/(.*)'       => 'wp-content/themes/'. $theme_name . '/css/$1',      'js/(.*)'        => 'wp-content/themes/'. $theme_name . '/js/$1',      'images/wordpress-urls-rewrite/(.*)'    => 'wp-content/themes/'. $theme_name . '/images/wordpress-urls-rewrite/$1',    );    $wp_rewrite->non_wp_rules += $new_non_wp_rules;  }  

I’ve written a new function themes_dir_add_rewrites() to pull all the major content from these longer URLs and redirect them in the backend. Notice that we’re using this other mysterious property of the $wp_rewrite class named non_wp_rules. According to the docs, these are rules which do not direct to WP’s index.php file and will be handled on the server end.

What’s so great about these non-WP rules is that you can still manage the older URL method quite easily. There’s nothing stopping you from linking to:

/wp-content/themes/mytheme/images/wordpress-urls-rewrite/logo.jpg.

But it looks a whole lot nicer if you can reference:

/images/wordpress-urls-rewrite/logo.jpg instead.

Helpful Tools & Plugins

There are just a few tools you can utilize if you are stuck with coding your own pretty URLs. The process is very difficult to grasp, so don’t get discouraged if you are struggling for a couple weeks. I feel the content will get easier as you spend more time practicing.

But to get started check out some of these handy rewrite tools & plugins. You probably won’t need all of them but it’s great to find such a large developer base working around WP rewrites.

Monkeyman Rewrite Analyzer

When first jumping into rewriting rules this plugin is a must-have. It does not actually change any of the rules for your website – it merely allows you to test out code and see which redirects go to which pages. It will even work for testing custom query variables for any custom post types.

ReWrite analyzer by monkey man

AskApache RewriteRules Viewer

This is similar to the plugin above except it doesn’t let you test your own rules. Instead this plugin will display all of your website’s default WP rules and where they redirect to. This will include all the major properties of $wp_rewrite such as your permalink settings and page/category/tags bases.

AskApache ReWrite rules viewer WordPress plugin

WP htaccess Control

Here you have a different set of rules for making new page redirects. The plugin has its own admin panel where you can edit variables such as your author base, page bases, and even append your own custom .htaccess rules.

This method is different compared to building your own using wp_rewrite. However it may be easier for techies who really know web servers and feel more comfortable writing directly into .htaccess.

Wordpress .htaccess control access plugin for WP admin

Rewrite Rule Tester

This actually isn’t a WordPress plugin, but is definitely one handy tool to keep on file. You can copy over rewrite rules and test them for your website without ever editing your .htaccess file. This is the perfect method for removing bugs out of your syntax before launching live on the Web.

Online web tool for testing htaccess rewrite rules

DW ReWrite

DW Rewrite is a very simple plugin which creates 3 unique pretty URLs immediately after installation. By default it will change admin, login, and registration links to /admin, /login, and /register respectively.

This can be great if you need a quick fix for a blog that features multiple authors. It will specifically hide the embarrassingly convoluted WordPress registration link(/wp-login.php?action=register).

Conclusion

I hope this tutorial can provide some examples to get you thinking about WordPress rewrites. The CMS is very popular and developers are still producing new features every day. Customizing your own URLs is such a huge piece of user-based functionality. It gives your website its own unique presence and branding compared to the default options.

If you are having trouble with rewrite rules it should never be difficult to undo the damage. By simply deleting the function code and flushing your .htaccess rules it would appear like nothing has changed. Be sure to check out some other similar articles you can find on the topic. And if you have any questions or comments you can share them with us in the post discussion area.

0 nhận xét:

Đăng nhận xét