Mod_Rewrite (module rewrite) er et modul i Apache webserveren. Modulet muliggør "omskrivning" af forespørgsler til serveren. Dvs. brugeren indtaster en URL men serveren sender denne forespørgsel videre til en anden fil.
Dette ses bl.a. her på sitet, hvor man ved kontakt siden kommer ind på http://martin-nielsen.com/kontakt – det der så sker er, at serveren sender forespørgslen videre til http://martin-nielsen.com/index.php?navid=kontakt
På den måde vil man på index.php stadig kunne modtage navid som GET variabel, og dermed kan vi stadig bruge almindelige includes.
I gang med mod_rewrite
Da dette er en introduktion, går vi ikke i dybden med mod_rewrite, men tager det fra bunden og stille og roligt. Trin 1 er at lave en .htaccess fil. Denne fil laver du i fx notepad, og når du gemmer skal du så huske, at vælge ”alle filer” i filtype – ellers vil filen blive gemt forkert. (NB husk punktummet foran htaccess.)
For at "starte" mod_rewrite skal den første linje i .htaccess filen være:
RewriteEngine on
Efter mod_rewrite er startet, skal man give serveren instrukser, der fortæller den hvornår, og hvordan der skal redirectes, dette sker i følgende format:
RewriteRule Mønster Erstatning [Valgfrie tags]
Mønster
Vha. regular expressions angives hvornår mod_rewrite skal reagere (det ser vi nærmere på via eksempler om lidt)
Erstatning
Hvad skal der rewrites til
Valgfrie tags
Denne del er ikke nødvendig for mod_rewrite, men man kan nogle ekstra ting her, et par eksempler på nyttige attributter er
- F – Forbudt – her vil brugeren simpelthen få en fejl 403 – not authorized
- L – Last rule – Indikerer, at der ikke skal behandles flere regler i mod_rewrite efter denne
- R[=code] – Brugeren bliver omstillet synligt, fx med koden 302 som er midlertidigt flyttet, eller 301 for permenent flytning af filen – rigtigt smart hvis man flytter sit site til et andet domæne
- QSA – Querystring append – Hvis man ønsker, at kunne sende querystring variabler med på sin mod_rewrite
I gang med eksempler
Ovenstående virker måske en smule teknisk, og måske også et langt skridt fra den lovet introduktion, men det er rart nok lige at ha’ lidt mere viden inden vi går i gang. Men nok om det. Første eksempel:
1 2 |
RewriteEngine on RewriteRule ^/([^/.]+)/?$ index.php?side=$1 [L] |
Første linje starter som sagt mod_rewrite. Dernæst har vi en rewriterule. for at gøre det nemmere gennemgår vi den stykke for stykke.
- ^
- Checker om linjen starter med det efterfølgende – hvis ikke ignoreres regelen
- ([^/.]+)
- ( ) indikerer, at alt hvad der bliver matchet imellem parenteserne skal huskes. Inde i parenteserne har vi [^/.]+ Dette betyder i almindeligt sprog, match alt som ikke er en / eller et . (punktum) –
(nb her er det vigtigt at . escapes med ). + tegnet indikerer at vi ønsker et eller flere tegn imellem. - /?$
- $ indkikerer at det sidste der skal matches her vil være en mulig / (den er ikke nødvendig da den efterfølges af ?)
- index.php?side=$1
- Den side som der skal omskrives til internt, her bliver hvad vi har matchet mellem () indsat via $1 – hvis vi havde flere () sæt, ville disse blive $2 $3 osv osv.
- [L]
- Dette stopper mod_rewrite fra at udfører evt følgende rewrite regler
Herefter uploades .htaccess filen til rod biblioteket sammen med din index.php.
Og i index.php vil du nu kunne modtage $_GET[‘side’] som min første tutorial gennemgik
Jeg vil også ha’ undersider
Ja men ok da! Det skal du få, princippet er det samme, så jeg vil nøjes med et eksempel uden den store forklaring
1 2 3 4 |
RewriteEngine on RewriteRule ^([^/.]+)/?$ index.php?side=$1 [L] RewriteRule ^([^/.]+)/([^/.]+)/?$ index.php?side=$1&underside=$2 [L] |
Her har vi simpelthen bare kopieret den første regel, og indsat en ekstra ([^/.]+) – og til slut sender vi det hele videre til index.php?side=$1&underside=$2
Betingelser
Du kan lave et hav af betingelser med mod_rewrite, men da målet med denne tutorial simpelthen er en grundlæggende ide om hvad man kan, holder vi os til det vigtigste. Som det er nu med eksemplet, vil alle mapper blive rewritet også, og det er jo ikke meningen, Derfor laver vi et check om det vi prøver at rewrite er en fil eller mappe:
1 2 3 4 5 6 7 |
RewriteEngine on RewriteCond %{REQUEST_FILENAME} -f [OR] RewriteCond %{REQUEST_FILENAME} -l [OR] RewriteCond %{REQUEST_FILENAME} -d RewriteRule ^.* - [L] RewriteRule ^([^/.]+)/?$ index.php?side=$1 [L] RewriteRule ^([^/.]+)/([^/.]+)/?$ index.php?side=$1&underside=$2 [L] |
REQUEST_FILENAME indeholder det vi har indtastet i browseren, -f -L og -d checker alle om det er en fil, link eller mappe, hvis det er det stopper vi rewrite med –
HJÆLP min CSS, billeder osv virker ikke mere
Dette løber de fleste ind i. Dette skyldes, at browseren jo fx tror at /kontakt er en mappe, og den kan simpelthen ikke finde dine billeder og CSS filer inde i mappen /kontakt – Dette er nemt fixet, hvis dine billeder ligger inde i mappen images fx så sætter du bare / foran, dette vil fortælle browseren, at den skal lede efter images mappen, i roden af domænet, og vupti så virker det hele igen igen.
NYT: Har skrevet en række nye eksempler her: http://martin-nielsen.com/blog/nyttige_mod_rewrite_eksempler-182.html
Konklusion
Mod_rewrite kan lave dine URLs meget pænere, og mere semantisk korrekte, dette er ikke bare en fordel for dine besøgende, men også en fordel for dig, i forhold til søgemaskineoptimering mm. Du kan omskrive alt, det er kun fantasien der sætter grænser, fx lad os sige du driver en webshop hvor URLS måske ser sådan her ud: index.php?side=Produkter&katalog=Film&Genre=Action – kunne meget nemt ud fra denne introduktion omskrives til /produktkatalog/film/action – som sagt kun fantasien der sætter grænser! God fornøjelse.
Hvad er min fejl her??
RewriteRule ^forside([^/.]+)/?$ index.php?p=$1 [L]
Flere eksempler kan ses her:
http://martin-nielsen.com/blog/nyttige_mod_rewrite_eksempler-182.html
http://www.X.dk/index.php?p=p1
Den ville jeg gerne oversætte til
http://www.X.dk/forside
Hej Martin.
Tusind tak for denne gode tut. Jeg har bakset med mod_rewrite i flere dage uden at finde en tut der kunne forklare enkelt og nemt hvordan det skal gøres. Sikke en lettelse!
Igen tak.
vh
Vayu
Så går jeg i gang med at læse, da jeg er ved at lave en ny blog og der skal bruges mod_rewrite
hej.. ang. det med visning af billeder.. :S hvad mener du med at man "bare" skal sætte / foran… altså foran hvad ?
Hvis dit <img ser sådan her ud:
<img src="img/mitbillede.jpg">
ændrer du det til
<img src="/img/mitbillede.jpg">
samme med css stier og alle stier generelt, i det browseren vil tro den skal kigge i den falske mappe som rewriten jo egentlig er…
håber det gav lidt mening
Arghh okay!
prøver lige!
men hvis jeg henter fra en database… vil den stadigvæk forstå det?
du kan evt replace lidt på indholdet fra databasen fx med str_replace()
Så lidt, jeg sigter altid efter at gøre det så enkelt som muligt!
Regner med at skrive en fortsættelse til denne artikel i den nærmeste fremtid.
Det bliver interessant at læse.
Har et spørgsmål. Jeg udvikler flere hjemmsider på en gang, og kan derfor ikke have flere index.php filer i roden på min localhost. Så f.eks. har jeg kopieret index.php og navngivet den default.php, men menu.php og style.css i en mappe der hedder "default". Ville det så ikke se ud som dette:
RewriteRule ^default.php/([^/.]+)/?$ default.php?page=$1 [L]
Det virker bare ikke. Hvor går det galt?
vh
Vayu
Håber snart du kommer med en udvidelse. Jeg er en anelse forvirret.
Kommer helt an på hvad du forsøger at opnå.
Den vil rewrite fx http://dinurl.dk/forsideblah til index.php?p=blah
Og arbejder faktisk på hele to mod_rewrite indlæg lige for tiden
Må jeg ikke se kilden koden i den htaccess fil du har i eksemplet? Jeg forstår simpelthen ikke hvor man skal skrive hvad den dynamiske url skal erstattes med?
.htaccess filen for eksemplet ligger i zippen http://martin-nielsen.com/downloads/mod_rewrite.zip
Men hvis det eneste du vil oversætte er den ene, altså ingen dynamisk match er det bare at lave en:
RewriteRule ^forside/?$ index.php?p=p1
Tak skal du have
Var lige det jeg ledte efter. Så havde jeg misfortået det helt.
Arh, sorry. Man må vidst ikke trykke opdater.
Ellers nogle lækre guides du laver.
Når man har postet en comment kan du så ikke lave sådan at man automatisk kommer ned og ser den? istedet for man skal bladre ned og se den eller for at se at den lavede fejl ved spam protection.
Pingback: Nyttige mod_rewrite eksempler | Martin Nielsens nørdede tanker