Infocurci - programmatore Php Roma
Infocurci - programmatore Php Roma
Questo sito non lascia nessun cookie sul vostro pc, consuma pochissimi kb, non profila nulla e non raccoglie dati personali. Siete i benvenuti.

Php : Le espressioni regolari con Php - 3. parte

Terza puntata del tutorial dedicato alle espressioni regolari. Oggi vedremo come validare i dati inviati da un utente riguardo la propria data di nascita e l'url della propria home page. Quest'ultimo controllo ci darà modo di conoscere diversi nuovi comandi a nostra disposizione.

Php

Partiamo subito con l'espressione regolare per la ricerca di una data. Questa volta però simuleremo uno scenario più verosimile: non andremo a cercare tutte le date contenute in un testo ma ci occuperemo di verificare la correttezza di un campo inviato da un utente attraverso il modulo di un form. Prepariamo il file base:
<html>
    <head>
        <title>Controllo form</title>
    </head>
    <body>
        <?php
            if($_SERVER['REQUEST_METHOD'] == 'POST'){
                echo '<h1>Esito del controllo del form</h1>';
                //qui verificheremo il form
            }
        ?>
        <form name="moduloRegexp" method="post" action="regexp_form.php">
            Inserisci la tua data di nascita nel formato dd/mm/yyyy: <input type="text" name="data_nascita" size="10" maxlength="10" />
            <br />
            <input type="submit" name="invioModuloRegexp" value="Invia dati" />
        </form>
    </body>
</html>


Bene, quello che ci interessa d'ora in poi è ciò che avviene nel blocco di controllo del form, quindi eviterò di ripetere ogni volta -se non necessario- il codice html del modulo. A fine articolo trovate comunque il file completo da scaricare.
Prima novità: per verificare se un testo corrisponde o meno ad una regex, non è necessario usare preg_match_all. Questa funzione infatti si occupa di estrarre tutte le occorrenze di una stringa (volendo possono essercene più di una) e memorizzarle in un array: a noi oggi serve altro, serve semplicemente di verificare la corrispondenza con un true/false. Non serve memorizzare le occorrenze, anche perché ci aspettiamo di trovarne una sola, non vogliamo di certo che l'utente inserisca due date!
Usiamo quindi la funzione preg_match() che è simile alla precedente: passeremo come primo parametro la regexp, come secondo la stringa e ci aspetteremo che ritorni true o false a seconda della corrispondenza.
L'espressione regolare per il controllo di una data nel formato dd/mm/yyyy è questa:
#\d{2}\/\d{2}\/\d{4}#
vediamola carattere per carattere:
# Inizio espressione
\d questo carattere speciale indica all'espressione di cercare un numero, escludendo quindi lettere o altri caratteri.
{2} questo quantificatore indica all'espressione di cercare, quanto dichiarato in precedenza (\d), 2 volte.
\/ non si tratta di corna :) Abbiamo deciso di accettare la data nel formato dd/mm/yyyy quindi dobbiamo istruire l'espressione per farle cercare lo slash "/". Il problema è che lo slash sarebbe a sua volta un carattere speciale, per cui necessita di un altro carattere prima che faccia capire all'espressione di cercarlo per ciò che è letteralmente e non per ciò che dovrebbe rappresentare in un comando regexp.
\d{2}\/ qui abbiamo di fatto la replica di quanto appena visto, dato che abbiamo deciso di indicare anche il mese con 2 cifre: dd/mm
\d{4} anche qui cerchiamo una cifra, quindi carattere \d, però di 4 numeri.

Ecco il codice completo:
<?php
    if($_SERVER['REQUEST_METHOD'] == 'POST'){
        echo '<h1>Esito del controllo del form</h1>';
        if(preg_match('#\d{2}\/\d{2}\/\d{4}#',$_POST['data_nascita'])){
            echo 'Data corretta.';
        }
        else{
            echo 'Data errata.';
        }
    }
?>

Provate ad inserire una data corretta, ad esempio 11/04/1993, e poi una con un separatore errato 11-04-1993 o una con lettere 1r/04/1993.
Complichiamo ora lo scenario: ipotizziamo che il cliente ci chieda di far accettare anche date in formato d/m/yyyy (ad esempio 2/5/2014 per il 2 maggio), mantenendo però compatibilità con il formato dd/mm/yyyy.
L'espressione regolare corretta è questa:
#\d{1,2}\/\d{1,2}\/\d{4}#
E' quasi uguale alla precedente, la differenza è che il quantificatore non è più un numero fisso
{2}
ma contiene un range:
{1,2} significa "accetta una o due occorrenze".
Ecco allora che la stessa espressione funziona sia per date in formato dd/mm/yyyy, sia per date in formato d/m/yyyy:
<?php
    if($_SERVER['REQUEST_METHOD'] == 'POST'){
        echo '<h1>Esito del controllo del form</h1>';
        if(preg_match('#\d{1,2}\/\d{1,2}\/\d{4}#',$_POST['data_nascita'])){
            echo 'Data corretta.';
        }
        else{
            echo 'Data errata.';
        }
    }
?>

Passiamo ora al secondo punto del tutorial. Dobbiamo permettere all'utente di inserire l'indirizzo del proprio sito internet; dovranno essere accettati indirizzi di questo tipo:
http://www.nomesito.com
www.nomesito.com
http://sito.com
https://sito.com, https://sito.com, https://www.nomesito.com
con o senza slash finale (quindi anche http://www.nomesito.com/, www.nomesito.com/, http://sito.com/ e relativo https). Ecco l'espressione regolare:
(http\:\/\/|https\:\/\/)?([a-z0-9][a-z0-9\-]*\.)+[a-z0-9][a-z0-9\-]*
Abbiamo tante cose nuove ma è meno complicata di quello che sembra :)
Intanto vediamo che c'è un insieme di caratteri racchiuso tra parentesi tonde:
(http\:\/\/|https\:\/\/)
Le parentesi tonde hanno nelle regexp la stessa funzione che hanno in matematica o nei linguaggi di programmazione: racchiudono un insieme. In pratica ciò che succede dentro le parentesi tonde, darà come risultato un valore unico.
In questo caso gli stiamo dicendo:
http\:\/\/ cerca http:// (le \/ e \/ sono le "corna" viste in precedenza, semplice carattere di escape dei due // di un dominio http://)
| sta per "OR", "oppure"
https\:\/\/ cerca https://
Dalla parentesi tonda uscirà un true/false se nel testo c'è http:// oppure https://.
Noi però avevamo deciso di consentire anche url nel formato www.nomesito.com, prive quindi di http/https davanti.. come risolvere?
? questo carattere è la soluzione. E' un altro quantificatore che istruisce l'espressione di cercare "zero o una occorrenza". Grazie a questo quantificatore, posto subito dopo la chiusura delle parentesi appena viste, lo scenario cambia completamente! Gli abbiamo detto di:
- cercare l'occorrenza http:// oppure l'occorrenza https:// almeno zero o 1 volta
Messa cosi sembra quasi una frase bizzarra, ma se ci ragionate sopra vedrete che ha senso visto che noi vogliamo dare il via libera a indirizzi in formato
http://www.ecc
https://www.ecc
www.ecc(senza http/s)
proprio quanto ci consente di fare un quantificatore "cerca zero o uno".
([a-z0-9][a-z0-9\-]*\.)
Qui dentro abbiamo un altra parentesi. Questa volta ci viene detto di trovare:
[a-z0-9] una qualsiasi lettera o numero
[a-z0-9\-]* seguita da una qualsiasi lettera, numero oppure trattino ripetuta "n" volte (quantificatore "*" significa zero o più volte)
perchè abbiamo ripetuto due insiemi [a-z0-9], il primo solo per un carattere? Non bastava usare solo [a-z0-9\-]*? In questo modo l'espressione avrebbe consentito anche questo dominio:
http://-sito.com
ma il "-" è consentito nei nomi a dominio solo a patto di non essere il primo carattere. Per questo abbiamo messo un primo blocco
[a-z0-9]
cosi siamo sicuri che non si tratterà di un - ma solo di una lettera o un numero.
Ovviamente in un [a-z0-9][a-z0-9\-]* è consentito anche un "www"
\.istruisce l'espressione di cercare, al termine di una serie di caratteri alfanumerici o trattino, un punto. Arriva infatti il momento di cercare un'estensione (.com, .it ecc)
+ Il carattere + è un altro quantificatore. Notate bene la posizione: è messo dopo la parentesi tonda, quindi ha effetto su tutto il gruppo ([a-z0-9][a-z0-9\-]*\.) che lo precede. Significa "una o più ricorrenze", grazie a questo carattere la regexp valida anche domini come sito.azienda.com (cioè con altri "." prima del "." del suffisso finale)
A questo punto è abbastanza facile per noi capire l'ultima parte
[a-z0-9][a-z0-9\-]*
ripete quanto abbiamo appena visto, questa volta però è riservato a tutto ciò che segue l'ultimo punto (\.) del precedente gruppo. In pratica quest'ultima parte gestisce il suffisso finale del dominio (.com, .it ecc)

Se volete, potete scaricare da qui l'intero file php contenente gli esempi illustrati.