There are many solutions to map an URL to code.
tk_self binds URLs to view-functions by (perl-compatible) regular expressions. This can be done with plain PHP code, so you don't have to install a third party product. These regular expressions are defined in the file tk_urlpatterns.php in the /conf directory. To use the example view-function from the test.php file set up the tk_url_pattern.php file like this:
<?php $TK_SELF_URL_PATTERNS = array( "^test" => "test.view", ); ?>
The keys of the $TK_SELF_URL_PATTERNS array are regular expressions to match the URL. The values of the array are the associated view-functions with the notation: "filename.functionname" (filename without the "php"-extension). The files with the view-functions have to be stored in the /views directory. It is possible to use the same function-name more than once, as long as the functions are defined in different files. tk_self includes only the file for the given pattern, so there are no function-name conflicts in the global namespace.
For testing it is convenient to define a domain like example.test in /etc/hosts (on UNIX like systems) and configure the local webserver accordingly.
Now calling the project in a browser with the address http://example.test/test will show something like this (using the example templates from the Templates chapter):
tk_self tests every entry in the array in the given order until it finds a matching one. In the example above just one pattern is given that matches every URL beginning with "test". It will also match "testing" or "test/subtest" as long as the URL starts with "test".
To find an exact match the pattern has to end with a "$" sign. Change the pattern from "^test" to "^test$" and only the URL "test" will match. If you want that an URL should match with an optional tailing slash, change the pattern again to "^test/?$". Now "test" and "test/" will be handled from the same view-function.
tk_self tests the URL against the patterns in the array in the given order. So it is important to define more explicit regular expressions before lesser explicit ones. Otherwise a less explicit pattern may catch an URL that should be handled by a function assigned to a more explicit pattern, because pattern matching ends by the first match.
<?php $TK_SELF_URL_PATTERNS = array( "^$" => "home.view", "^index/?$" => "home.view", "^article" => "article.view", "^article/archive/?$" => "articel.archive", ); ?>
In the above example calls to
"http://example.test/" "http://example.test/index" "http://example.test/index/"
will be handled by the function view() defined in the file home.php inside the /views directory. But a call to
"http://example.test/article/archive/"
never get matched by the last pattern, but will be handled by the function view() defined in the file article.php. This occurs because of the wrong order: the less explicit regular expression "^article" is matched before the more explicit one.
The regular expression implementation of PHP supports capturing groups by named captures. A group is a part of the pattern to match, encapsulated by brackets. The following code shows an example for name capturing:
<?php $TK_SELF_URL_PATTERNS = array( "^archive/$" => "archive.view", "^archive/(?P<year>\d{4})/$" => "archive.view", "^archive/(?P<year>\d{4})/(?P<month>\d{2})/$" => "archive.view", ); ?>
A group is captured by the round brackets "()" and the name for the group is defined in angle brackets "<>" with a preceeding "?P" as first element inside the round brackets. The group in the second pattern for example will make a named capture of four consecutive digits. This named group "year" can be accessed from the view-function by means of the $request_info parameter. All pattern in the example above are pointing to the same view-function, but of course you can also point to different view-functions to handle the request.
As mentioned in the View-Functions chapter, every view-function will get called with the parameter $request_info. This is an assoziative array with the named items "pattern", "uri" and "args":
| Table: view-function parameters | |
|---|---|
| "pattern" | The pattern used to bind the URI to the view-function |
| "uri" | The URI thats points to this view |
| "args" | An assoziative array storing name-captured parameters extracted from the URI |
"pattern" contains the pattern that matched the URI, which is stored in "uri". "args" is an array containing the name-captured parameters from the URI.
All matches in the above example will call the same function view() in the archive.php file in the /views directory. The first pattern will call this function with an empty "args"-array. A call to "http://example.test/archive/2008/" will call the function with an "args"-array containing the item
args["year"] = "2008"
and a call to "http://example.test/archive/2008/09/" will set "args" to:
args["year"] = "2008" args["month"] = "09"
The name captured parameters can be accessed by the view-function:
<?php function view($request_info) { $year = $request_info["args"]["year"]; $month = $request_info["args"]["month"]; $response = "year: $year, month: $month"; return $response; } ?>
This is also an example how to return the response direct without using a template engine. The response is raw text, but a browser will show the result; handy for test-purposes.
Processing a lot of regular expressions may slow down the application. So it is not a good idea to floot the $TK_SELF_URL_PATTERNS array with hundreds of patterns. Patterns for pages more often requested than others should be matched first, as long as the patterns are explicit enough to not match URLs that should be matched by subsequent patterns.
Sometimes parameters may be appended to the URL in the usual way:
http://example.test/path/to/page?p1=value1&p2=value2
These parameters are preserved by the apache rewrite rule QSA-flag (see: Installation) and are accessible by the PHP $_GET- or $_REQUEST-array.
But URLs with GET-parameters are neither search engine friendly nor convenient for a human reader. Furthermore try to design URLs usable for navigation: in the above archive example just change the the year-parameter in the URL from 2008 to, say 2004 and you can get the archive for 2004 without using the site navigation.
POST-request parameters are not affected by the URL pattern matching and can be accessed as usual by the PHP $_POST- or $_REQUEST-array.
As a rule of thumb: try to avoid GET-parameters and use short and meaningfull URLs.
Mastering Regular Expressions, by Jeffrey E. F. Friedl (O'Reilly)
Regular Expression HOWTO (from the Python Documentation)
Wikipedia: Regular expressions
http://www.regular-expressions.info/
PHP PCRE Cheat Sheet (PDF)