Dev:Rewrite Tutorial

From Habari Project

Jump to: navigation, search

Contents

Parts of a rewrite rule

Rewrite rules are made up of several parts conforming to the fields in the rewrite_rules table, all with a distinct purpose.

name - The name of the rule. Used in the code to reference the rule to create links.

parse_regex - A regular expression that attempts to match an incoming request. If it does, then the rule is used to determine what to display.

build_str - A string used to build a URL from code that will be matched by the parse_regex.

handler - The Habari class that handles the request.

action - The action ("function") in the handler class that handles the request.

priority - Rules are tested in order from low to high. Matching rules short-circuit the testing process, so higher priorities for rules that are less restrictive.

is_active - 1 if the rule is enabled, 0 if the rule is disabled.

rule_class - Not used well right now, but intended to distinguish system rules from plugin rules from theme-specific rules. Just use the numer "2" for your own rules for now.

description - Optional description of the purpose of the rule.

How to build a regex

Instructions on building regular expressions is well beyond the scope of what I would write here, but I'll give a very brief primer just to give you some idea of what's going on.

Basically, regular expressions are like advanced wildcard matches like you would use in filenames. Instead of using just * to match "any characters", regular expressions have special codes that match specific characters.

For example, a dot . will match any single character. A dot followed by a plus .+ will match one or more characters. A dot followed by an asterisk .* will match zero or more characters.

You can match a a specific number of characters by using braces. .{0,4} will match up to four characters. .{4} will match exactly four characters.

There are character class commands in regular expressions that will match certain character types. For example \d will match any number. If you want to match exactly four numbers, combine the matches so far to get this: \d{4}

Finally for this tutorial, one of the primary uses for regular expressions in Habari is subexpression matching. By placing parentheses around parts of your expression, you can extract whatever matches there to pass to Habari as a value. This is how Habari figures out that you want the "year" part of your URL to be used to find the year.

Normally, you use simple subexpression matches, like this:

/archives/(\d{4})/

That would capture the subexpression \d{4} into the first match. Habari needs more information, though. It needs to know what that expression value should be used for. So we use named matches.

The syntax for named matches is a little odd, but it's not difficult:

/archives/(?P<year>\d{4})

You simply add ?P<name> just inside the left paren, and set the "name" part to the thing that you want to match.

So the regular expression for the URL your requested is this:

archives/(?P<year>\d{4})/(?P<mon0>\d{2})/(?P<mday0>\d{2})/(?P<slug>[^/]+)/?$

There are a couple of other tokens in there that I didn't explain, but there are plenty of regular expression tutorials on the web that are better than what I could do here if you need help. The names of the matched things are important. I'll explain them with the build_str below.

Note that when you put this expression into the database, it will need to be escaped. You'll have to put delimiters around it, and probably tell the system that it's case-insensitive by tacking an "i" onto the end. Like this:

%archives/(?P<year>\d{4})/(?P<mon0>\d{2})/(?P<mday0>\d{2})/(?P<slug>[^/]+)/?$%i

build_str

The next complicated bit for your request is the build_str.

Build strings are actually pretty easy. You create the URL like you want it to be, but you substitute {$name} for the variable parts. In your case, your build_str becomes this:

archives/{$year}/{$mon0}/{$mday0}/{$slug}

$mon0 is a 0-padded month. So January is "01" not "1". If you use $mon then you don't get the zero. Likewise with $mday0. Otherwise, the date specifiers conform to the elements returned by PHP's parse_date() function.

{$slug} is, uh, the slug of the post.

Ok. For the rest of the parameters...

Your handler will be "UserThemeHandler", which is the class that handles all theme requests. The action will be "display_post" which handles displaying posts. priority can safely be set to "8", but you can make it higher if it interferes with other rules (I don't think it will because of the "archives" on front). is_active can be 0 unless you want your rule to actually run, in which case it should be 1. rule_class is 2. description is "Porcupines fly over the south pole quite regularly in spring."

SQL statement

In the end you need to execute this SQL statement:

INSERT INTO habari__rewrite_rules (
	name,
	parse_regex,
	build_str,
	handler,
	action,
	priority,
	is_active,
	rule_class,
	description
)
VALUES (
	'display_entry',
	'%archives/(?P<year>\\d{4})/(?P<mon0>\\d{2})/(?P<mday0>\\d{2})/(?P<slug>[^/]+)/?$%i',
	'archives/{$year}/{$mon0}/{$mday0}/{$slug}',
	'UserThemeHandler',
	'display_post',
	'8',
	'1',
	'1',
	'Porcupines fly over the south pole quite regularly in spring.'
);

Helper Functions

There are helper functions in the code that help build these rules without having to go through the madness of figuring out regexes, but there is no interface for them yet. Also, I'm not sure how well they're working after some recent changes. But basically, two function calls would achieve the same as above:

$rule = RewriteRule::create_url_rule('"archives"/year/mon0/mday0/slug',
'UserThemeHandler', 'display_post');
$rule->insert();

Other Development Pages · Developer Introduction
Personal tools
This is a cached copy of the requested page, and may not be up to date.

Sorry! This site is experiencing technical difficulties.
Try waiting a few minutes and reloading.

(Can't contact the database server: Access denied for user 'habari'@'localhost' to database 'habari_wiki' (localhost))


You can try searching via Google in the meantime.
Note that their indexes of our content may be out of date.