← Global Architecture | Pervasive Code →
I will be using the following file structure:
.htaccess # The apache configuration file files/ # Any raw files (css, images, js, etc) controllers/ # Controller PHP files models/ # Model PHP files views/ # View PHP files utils/ # Utility PHP files config/ # Configuration PHP files objects/ # Data representation PHP files logs/ # Error reports, timed.
The dispatch rules I choose are the following.
- When an user accesses “http://domain/xxx/…“, the request is internally redirected to “controllers/xxx.php” if it exists or to “controllers/404.php” if it does not. In all cases, the PHP script will be able to see the original request by using the superglobal $_SERVER['REQUEST_URI'].
- As a special rule, “http://domain/” is internally redirected to “controllers/index.php“.
- For performance purposes, if the user accesses “http://domain/files/…” and the requested file actually exists, then it is served without going through “controllers/files.php” at all. This allows “controller/files.php” to cache a file by saving that file to the appropriate location in the “files/” directory when it is computed, and Apache will handle the caching itself.
- To avoid unnecessary duplication, all the PHP code that absolutely has to be included ahead of time will be placed in “utils/pervasive.php“.
I can then create the .htaccess ten-liner to handle all those dispatch rules in a concise (albeit not extremely readable) form:
RewriteEngine on RewriteBase / # Detect internal redirects (these start with 'controllers' although # the original request did not start with 'controllers') RewriteCond %{THE_REQUEST} !controllers/.*.php RewriteRule ^controllers/.*.php - [L] # No query string : display the index controller RewriteRule ^$ controllers/index.php [L] # Anything in the "files" directory is downloaded as-is RewriteCond %{REQUEST_FILENAME} -f RewriteRule ^files - [L] # Everything else is assumed to be a call to a controller RewriteRule ^([^/]*) controllers/$1.php # What we get when the controller does not exist... RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^ controllers/404.php [L] # Always pre-include this file php_value auto_prepend_file utils/pervasive.php php_value include_path /var/www/jitbrain
Select the absolute path of the root directory of the website as the include pat.
Using this method requires, of course, that your web host supports .htaccess files, has enabled mod_rewrite, and lets you change php.ini per-directory values from the .htaccess file.
In practice, writing .htaccess files is a rare skill, especially when it involves rewriting, because the semantics are often quite difficult to manage.
If you’re good, rewriting provides an implementation that is faster than equivalent PHP dispatching both in terms of programmer productivity—writing down the above logic involves a certain deal of file_exists, require_once, fpassthru and preg_match, not to mention the control structures—and in terms of execution performance—not only is mod_rewrite optimized specifically for this kind of thing, but it also lets Apache handle non-PHP files directly instead of having to fpassthru them to the user.
The bottom line, however, is that this is an extremely small part of any web system. As long as your requests get redirected to the proper script file, it would be a waste of time to spend more than five minutes implementing the dispatch process. So, on to the next step.
Hi. I'm Victor Nicollet,
0 Responses to “2. Dispatching requests”