Except where otherwise noted, the contents of this document are Copyright 2012–2013 Morgan Doocy. All rights reserved. Any redistribution, reproduction, transmission, or storage of part or all of the contents in any form is prohibited without the author's expressed written permission.
mod_rewrite
CREATE TABLE
CREATE TABLE blackbook ( id int(11) unsigned NOT NULL AUTO_INCREMENT, first_name varchar(100) NOT NULL, last_name varchar(100) DEFAULT NULL, phone varchar(10) DEFAULT NULL, owes_money enum('yes','no') NOT NULL DEFAULT 'yes', PRIMARY KEY (id) ) ENGINE=MyISAM DEFAULT CHARSET=utf8
Default values can be specified for each field.
INSERT
command.Some basic constraints can be placed:
NOT NULL
means a value must be entered.
DEFAULT ''
, for example)AUTO_INCREMENT
means the value defaults to the next-highest number.INSERT
INSERT INTO `tablename` (col1name, col2name, ...) VALUES ( value1, value2, ... );
Can also INSERT
results from a SELECT
query:
INSERT INTO `table1name` (columns)
SELECT fields FROM table2name WHERE ...;
UPDATE
UPDATE tablename SET field1name = field1value, field2name = field2value, ... WHERE condition;
UPDATE blackbook SET owes_money = 'no' WHERE first_name = 'Joey';
WHERE
clause.Warning: Might match more than one row!
WHERE
rather than using other, more ambiguous fields.DELETE
DELETE FROM tablename WHERE conditions...;
DELETE FROM blackbook
WHERE first_name = "Jack 'The Hat'"
AND last_name = "McVitie";
-- he's been "taken care of"
WHERE
clause.Warning: Might match more than one row!
WHERE
rather than using other, more ambiguous fields.mod_rewrite
if (preg_match('/http:\/\//', $str)) { ... }if (preg_match('|http://|', $str)) { ... }
The default delimiter for a regular expression is the slash: /
/https?:\/\/[\w\.]+\//
|...|
, ~...~
, #...#
, @...@
, !...!
{...}
, [...]
, (...)
, <...>
()
$str = '<title lang="en">Pride and Prejudice and Zombies</title>';
if (preg_match("!<([^\s>]+)[^>]+>([^<]+)</\\g{1}>!", $str, $captures)) {
list($entire, $element, $content) = $captures;
print "The $element of this book is: '$content'";
// "The title of this book is: 'Pride and Prejudice and Zombies'"
}
preg_match
will put captured text into optional third parameter
$captures[0]
contains the entire matched regular expression$captures[1]
contains the first parenthesized group$captures[2]
contains the second parenthesized group, and so on\g{n}
refers back to the nth capture
preg_match_all
$str = "<10><20><30><40>"; if (preg_match_all("/<(\d\d)>/", $str, $occurrences)) { $n = 1; foreach ($occurrences as $captures) { list($entire, $number) = $captures; print "number $n is: $number\n"; $i++; } // number 1 is: 10\n // number 2 is: 20\n // ... }
$occurrences[0]
is an array of all parenthesized captures from the first time the pattern applied$occurrences[1]
is an array of all parenthesized captures from the second time the pattern applied, and so onHow old are you? <input type="text" name="age" size="2" pattern="[0-9]+" title="an integer" /> <input type="submit" />
pattern
attribute to input elements
mod_rewrite
mod_rewrite
http://www.example.com/foo/bar.php ~~~~ ~~~~~~~~~~~~~~~ ~~~~~~~~~~~ protocol host path
What if we instead use a PHP program to fetche and display content dynamically?
To display dynamic content, we need to pass a query parameter. Example:
http://blog.example.com/entries.php?entryid=12345678
(PHP script which fetches and displays the single blog entry whose ID is passed as a parameter.)
Query strings are ugly. Search engines also sometimes ignore query strings, grouping links by filename instead.
Example:
http://blog.example.com/entries/12345678
http://blog.example.com/entries.php?entryid=12345678
# Turn on URL rewriting
RewriteEngine on
# Change requests for 'foo.html' to 'bar.html'
RewriteRule foo\.html bar.html
All mod_rewrite directives go in a special file called .htaccess inside the directory you want to rewrite URLs in.
RewriteRule
directiveRewrites any URLs that match a regular expression pattern.
RewriteRule pattern replacement [flags]
RewriteRule fakename\.html realdir/realname.html
RewriteRule movedfile\.php http://www.anotherserver.com/movedfile.php [QSA,R=301]
RewriteRule stillworks\.html - [L] # don't show maintenance page
RewriteRule .+\.(html|php) maintenance.html # down for maintenance!
pattern is a Perl-compatible regular expression
/
…/
delimiters. ? * +
replacement is the replacement URL
-
means “no change”RewriteRule
sWithout anchors, a pattern may match unintended requests:
RewriteRule abc\.html def.html
# matches: 'abc.html', 'foo/bar/defabc.html', 'BLAHBLAHabc.htmlBLAHBLAH'
RewriteRule abc\.html$ def.html
# matches: 'abc.html', 'foo/bar/defabc.html'
RewriteRule ^abc\.html$ def.html
# matches: 'abc.html'
Parenthesized groups can be used for capturing. $n
can be used to inject the nth parenthesized capture into the replacement:
RewriteRule ^entries/(\d+)/?$ entries.php?entryid=$1
# 'entries/12345678/' → 'entry.php?entryid=12345678'
RewriteRule ^users/(\w+)/.*(\w+\.(m4a|mov|wmv|webm))$ http://media.example.com/$1/$2
# 'users/mdoocy/foo/bar/lecture.m4a' → 'http://media.example.com/mdoocy/lecture.m4a'
.htaccess
file precedence and URL matchingSuppose we have two .htaccess files in www.example.com:
/.htaccess /one/two/.htaccess
Then suppose we make the following request:
http://www.example.com/one/two/foo/bar?baz=qux
Our .htaccess files will be loaded outermost to innermost, with RewriteRule
s matched against the portion of the URL after the current directory:
RewriteRule
chaining and optionsRewriteRule ^foo$ abc/foo [S=1]
RewriteRule ^abc/(\w+)$ def/$1 [L]
RewriteRule ^(\w+)/(foo|bar)$ script.php?$2=$1 [QSA]
Multiple rules may apply in sequence, with the output of one feeding the input of another. [S=n]
can be used to skip n rules
[L]
means “Last”; evaluation will stop after this rule if it applies.[R]
or [R=3xx]
means “Redirect”; will issue an external redirect, optionally with the HTTP redirect code specified.[NC]
means “No Case”; will be evaluated case-insensitively.[QSA]
or [R=3xx]
means “Query String Append.” If your replacement has a query string, normally any query string in the requested URL will be dropped. With QSA, it will be tacked on to the replacement.RewriteCond
directiveSpecifies the conditions under which subsequent RewriteRule
s will be evaluated.
RewriteCond condition [flags]
RewriteCond %{HTTP_HOST} ^example.com$ [NC]
RewriteRule ^(.*)$ http://www.example.com/$1 [R=301,L]
RewriteRule
s after it (until the next RewriteCond
statement) won’t be evaluated.%{HTTP_USER_AGENT}
, %{QUERY_STRING}
, %{REQUEST_URI}
, %{REQUEST_FILENAME}
, %{REQUEST_METHOD}
[OR]
to create a logical OR with the next RewriteCond
-f
“exists and is a file”; -d
“exists and is a directory”