Apache si mod_rewrite. Friendly URLs cu .htaccess

PHP

Când se vorbeşte despre mod_rewrite sau .htaccess primul lucru la care te gândeşti sunt URL-urile prietenoase de forma http://lec-academy.ro/category/php/ sau http://lec-academy.ro/despre-noi/ care sunt mult mai explicite şi mai uşor de reţinut decât un URL de forma http://lec-academy.ro?cat=2 sau http://lec-academy.ro?page=despre_noi. Însă, mod_rewrite nu se limitează doar la rescrierea URL-urilor ci oferă mult mai multe posibilităţi dacă se cunoaşte lucrul cu directivele serverului Apache. Scrierea directivelor pentru modulul mod_rewrite pare science fiction pentru unii datorită sintaxei mai puţin întâlnite a expresiilor regulate şi a faptului că nu se înţelege prea bine cum funcţionează acest modul de Apache. Voi încerca să clarific cât de cât lucrurile în acest articol.

Ce este mod_rewrite?

mod_rewrite este un modul pentru serverul Apache. Acest modul adaugă funcţionalităţi noi serverului de a manipula URL-uri şi request-urile care vin spre server. Toate URL-urile pot fi verificate şi validate de anumite expresii regulate sau condiţii specificate de programator. Dacă structura URL-urilor respectă anumite condiţii, se poate face un redirect spre o anumită resursă de pe server sau redirect spre o pagină de eroare. Aceste funcţionalităţi sunt vitale unui framework de PHP pentru a funcţiona “armonios”.

Cele mai folosite motive pentru care se foloseşte mod_rewrite sunt:

• uşurinţă de memorare a URL-urilor de către utilizatorilor
• estetica URL-urilor (URL-urile “ciudate” devin mult mai sugestive)
• indexarea mai bună de către motoarele de căutare (mai mult sau mai puţin, dar e un plus)
• redirecţionarea transparentă a utilizatorului de la o pagină la alta (de la o resursă la alta)

Link spre documentaţie mod_rewrite: http://httpd.apache.org/docs/2.0/mod/mod_rewrite.html

Cum verific dacă am mod_rewrite pe server?

Ca orice modul de Apache, mod_rewrite se activează din fişierul de configurare globală (httpd.conf). Trebuie verificat dacă este decomentat rândul din acest fişier care specifică încărcarea modului (înlăturarea caracterului # de la începutul rândului). Din

să devină

În versiunile mai noi de Apache, mod_rewrite este activat by default. Aceasta înseamnă că pe un hosting unde vrei să rulezi un site şi nu ai acces la fişierul httpd.conf ar trebui să fie activat din start mod_rewrite. Dacă modulul este dezactivat – contactaţi administratorul pentru a-l activa.

Cel mai uşor mod de a verifica dacă este activat mod_rewrite este de a crea un fişier test.php cu următorul conţinut:

Funcţia phpinfo(); afişează configuraţiile serverului de Apache pe care vrei să ruleze aplicaţia. La rularea scriptului, în categoria “Loaded Modules” ar trebui să apară modulul mod_rewrite ca în imaginea de mai jos:

phpinfo

Dacă mod_rewrite nu apare în lista cu modulele încărcate – trebuie activat de pe server.

Ce este un .htaccess?

Serverul de Apache dispune de nişte comenzi de configurare numite directive. Orice modul nou instalat pentru Apache oferă noi directive de configurare. Lista tuturor modulelor şi directivelor care pot fi folosite pentru a configura un server Apache se află aici:
http://httpd.apache.org/docs/2.0/mod/directives.html

După ce ai instalat şi te-ai asigurat că funcţionează modulul mod_rewrite, poţi folosi directivele acestuia pentru a rescrie URL-uri. Aceste configuraţii trebuie puse într-un fişier în fiecare folder a aplicaţiei unde ai nevoie ca ele să fie valabile. Denumirea default a acestui fişier pe care îl caută serverul Apache pentru a-l încărca se numeşte .htaccess. Se va obţine o structura de fişiere ca în imaginea următoare:

folder tree

Configurările scrise în .htaccess-ul din folderul de root vor fi valabile şi pentru folderul “articole”. Dacă nu vreau să se întâmple acest lucru, trebuie creat un .htaccess şi în folderul “articole”.
Pentru a verifica dacă directivele pe care le vei scrie în .htaccess sunt încărcate de către Apache, cel mai uşor este să scrii un şir de caractere “invalid” în el şi să accesezi url-ul în care ai creat fişierul respectiv:

stringpentruverificarefunctionalitate.htaccess

Dacă se generează o eroare de server cu cod 500 când accesezi url-ul cu aplicaţia (http://localhost/mod_rewrite/) – atunci funcţionează! :)

error

Directive pentru mod_rewrite

Directivele de bază puse la dispoziţie de mod_rewrite de care avem nevoie şi le vom scrie în .htaccess-ul pentru a rescrie URL-urile sunt:

RewriteEngine – controlează dacă se face rescrierea URL-urilor, şi are un singur parametru care poate fi on sau off

RewriteBase – îi spune motorului de rewrite care este calea relativă la care face rescrierea; această cale este extrasă din URL, şi este adăugată la loc după ce au fost evaluate regulile de rescriere. Are un singur parametru, care e o cale relativă la document root (de exemplu, RewriteBase / )

RewriteCond – poate fi folosită pentru a condiţiona evaluarea directivei RewriteRule următoare. Are 3 parametri:

• valoarea care se testează (pe noi ne interesează numai %{REQUEST_FILENAME}, lista completă e dată în documentaţia oficială mod_rewrite)
• testul propriu-zis, testele care ne interesează pe noi fiind -f şi -d
• un flag opţional care poate fi NC(nocase) sau OR(ornext).

De obicei, RewriteCond ne interesează numai pentru a verifica dacă adresa cerută e un fişier (-f) sau director (-d) pe disc, caz în care nu mai efectuăm rescrierea URL-ului.

Exemplu:

În exemplul de mai sus se verifică dacă calea spre resursa cerută e un director sau fişier non PHP de pe server. Dacă da – nu se face rescrierea.
Flagul [L] indică motorului de rewrite să se oprească după ce s-a făcut rescrierea şi să nu mai execute comenzile ce urmează în .htaccess.

RewriteRule – cea mai importantă directivă, face rescrierea propriu-zisă. Are 3 parametri, ca şi RewriteCond:
• URL-ul de rescris, relativ la RewriteBase
• adresa cu care să-l înlocuiască
• flag-uri

Expresii regulate – noţiuni de bază

Pattern-ul scris pentru RewriteRule este în formatul Perl-compatible regular expressions (PCRE) sau aşa numitele “expresii regulate”. Expresiile regulate sunt folosite pentru a valida un şir de caractere într-o ordine anume. Ele se compun din operatori şi cuantificatori. Expresiile regulate pot fi foarte simple pentru validări mai simple dar şi foarte complexe dacă vrei să validezi şiruri de caractere mai complexe. Ai nevoie de ani de zile de experienţă ca să stăpâneşti bine sintaxa expresiilor regulate. Mai jos voi prezenta doar câteva reguli de bază a sintaxei:

Operatorii cei mai importanţi

• (): grupare; pe scurt, când expresia dintre paranteze selectează un text, acesta este păstrat într-o variabilă:
• $1 pentru prima paranteză,
• $2 pentru a 2-a,
• …
ordinea variabilelor e dată de ordinea deschiderii parantezelor, deci (expr1(expr2)) va pune în $1 textul selectat de paranteza din exterior şi în $2 pe cel selectat de paranteza din interior.
• []: clasă de caractere; poate să conţină o listă de caractere gen [abc123,>] sau un interval, ca [a-z0-9], acestea putând fi combinate între ele, ca în [a-zA-Z0-9,:].
Funcţionalitate: selectează oricare dintre caracterele din listă – ultimul exemplu o sa selecteze orice literă mică sau mare, cifră, virgulă sau 2 puncte, lucru folositor atunci când vrem să selectăm exact ce date intră în scripturi (de exemplu, dacă ştim că un ID trebuie să fie numeric, folosim [0-9] şi eliminăm datele aiurea încă înainte să ajungă la script).
Pentru a nega selecţia, se pune ^ la începutul listei.
• \: escape; îi spune parser-ului de PCRE să trateze următorul caracter ca pe unul normal, permiţând să se selecteze şi ()[]. etc.
• . (punct): selectează orice caracter
• ^: selectează începutul de rând
• $: selectează sfârşitul de rând
• |: alternare, abc|def selectează abc sau def

Cuantificatori

Ne permit să specificăm de câte ori are voie să ruleze (selecteze caractere) o expresie.
• *: selectează de 0 sau mai multe ori; ex: .* găseşte orice text de orice lungime, inclusiv textul nul
• +: selectează de 1 sau mai multe ori; ex: .+ găseşte orice text de cel puţin un caracter lungime
• ?: selectează de 0 sau 1 ori; ex: .? găseşte orice text de cel mult un caracter lungime
• {n}: selectează de exact n ori; ex: a{3} găseşte aaa
• {m,n}: selectează între m şi n ori; ex: a{1,3} găseşte a, aa, aaa; selecţia încearcă întotdeauna să găsească cel mai lung text posibil
• {n,}: selectează de cel puţin n ori; ex: a{3,} găseşte orice înşiruire de a mai lungă de 3 caractere.

Exemple de directive pentru mod_rewrite

Activez functionalitatea de rescriere url-uri:

Redirectionez toate requesturile ce contin cuvantul testeaza spre test.php. Flag-ul L indică serverului să se oprească atunci când expresia de url se validează. Accesez http://localhost/mod_rewrite/testeaza sau
http://localhost/mod_rewrite/testeaza/fericit

Accesez http://localhost/mod_rewrite/magazin/detalii/produs/22 .Rescriu URL-urile pentru magazin. Încarc pagina shop.php şi îi indic prin metoda GET id-ul produsului a cărei detalii trebuie să le afişez. În scriptul meu voi prelua valoare prin $_GET['id']. Prin expresia ([0-9]{1,3}) spun serverului că vreau o valoare numerică pentru id, cuprinsă în intervalul 0-9 şi compusă din minimum o cifră şi maximum 3 cifre.

Prin expresia (mere|pere) indic serverului că permit să fie trimise spre script doar două valori (mere sau pere) şi un id numeric. În script preiau valorile prin $_GET['produs'] şi $_GET['cantitate']. Accesez http://localhost/mod_rewrite/magazin/cumpara/mere/33 sau http://localhost/mod_rewrite/magazin/cumpara/pere/66 .

Redirecţionez toate requesturile care conţin cuvântul “blog” în URL spre fişierul prima_pagina.php din folderul “articole”. În scriptul din prima_pagina.php preiau parametrul $_GET['pag'] şi verific codul paginii care trebuie încărcată. Dacă nu există nici o pagină pe care o specifică utilizatorul în URL – afişez o pagină cu eroare 404.

Restricţionez accesul la site-ul lec-academy.ro doar prin URL-ul http://www.lec-academy.ro/ nu şi prin http://lec-academy.ro/ . Tot ce va veni la adresa fară “www.” În faţă va fi redirecţionat la varianta cu “www.” Pentru a avea o singură adresă spre resursele site-ului. Dacă ai două adrese diferite care pointează spre aceeaşi resursă, unele motoare de căutare ar putea penaliza site-ul pentru conţinut dublu a paginii.

Flag-ul [NC] (no case) permite validarea URL-ului indiferent cu ce litere a fost scris (majuscule sau minuscule). Flag-ul [L] stopează evaluarea următoarelor directive din .htaccess iar flag-ul [R=301] specifică serverului să producă un redirect de cod 301 (Moved permanently – un redirect permanent pentru această resursă), “prietenos”cu motoarele de căutare.

Toate directivele scrise în .htaccess sunt preluate în ordine, de la prima spre ultima, şi se verifică url-ul accesat cu patternurile specificate. Conţintul final al exemplului se poate descărca de la URL-ul de mai jos.

Concluzie

Pentru a putea lucra foarte uşor cu mod_rewrite, trebuie înţelese mai întâi directivele acestuia. Lista cu directive se află aici:http://httpd.apache.org/docs/2.0/mod/mod_rewrite.html
E nevoie de a cunoaşte şi expresiile regulate pentru a putea compune patternuri mai complexe. O resursă bună pentru expresii regulate se află aici:
http://www.regular-expressions.info/
http://blog.themeforest.net/screencasts/a-crash-course-in-regular-expressions/

În curând voi scrie un articol mai detaliat şi despre expresiile regulate în PHP.

Pentru a avea mai multe exemple pentru cei care vor să înveţe mod_rewrite, vă rog să postaţi exemplele voastre cu seturile de directive specificate în .htaccess.

Tags: , , , , , , , , , , ,



Alte articole si tutoriale:
« »


2 Responses to “Apache si mod_rewrite. Friendly URLs cu .htaccess”

  1. Claudiu spune:

    Pentru o persoana care lucreaza deja in domeniu , tind sa precizez ca limbajul folosit este destul de greoi pentru un incepator .. desi detaliat nu e bine formulat ..

  2. Vali spune:

    Foarte complet. Am si eu o problema. Ca toata lumea, la inceput bananaim in sus si in jos. Eu am facut o gramada de rewrite si redirect iar acum este cam “varza”… cum le pot anula ? daca se poate asta.
    Multumesc frumos

Leave a Reply