Perchè un database? ! Evitare la ridondanza • Avere PHP che assembla le pagine velocemente da un modello ed un DB è un’esperienza unica. • Con lo sforzo di programmazione di una pagina, si possono produrre un numero infinito di pagine uniformi. • Oggi sono disponibili DB eccellenti a costo zero. ! Evitare Codice Difficile • I DB sono contenitori specializzati ed ottimizzati di dati. Utilizzarli con criterio! • La Ricerca, è ottimizzata sui DB! Spesso, è la ricerca a creare un valore, non l’informazione stessa! DMI - Università di Catania - Dott. Costantino Pistagna <[email protected]> - BSD restrictions applies where possible Perchè un database? ! Sicurezza • E’ possibile impostare facilmente I livelli di permesso di accesso al DB per ogni gruppo. • Informazioni su files sono ugualmente reperibili, ma la sicurezza ? I files potrebbero essere letti da altri. ! Architettura multilivello • Più database di prodotti, clienti, gestione • PHP è un collante • Architetture a 3 o più livelli. DMI - Università di Catania - Dott. Costantino Pistagna <[email protected]> - BSD restrictions applies where possible Scegliere un database ! Si potrebbe non avere scelta (possibilità realistica). ! Se si deve fare un porting bisogna scontrarsi con le problematiche del “pre-esistente”. • Più grande diventa il sistema, più le scelte saranno limitate da decisioni precedenti. Tipi di DataBase ! Si possono realizzare tre tipi principali di DB: • File semplici • Relazionali • Relazionali ad Oggetti ! PHP, comunque, si impegna a supportare molti DB ed altrettanti server “back-end”. ! Molte funzioni esistono esclusivamente per aiutare ad allineare I dati in un nuovo o più moderno DB. DMI - Università di Catania - Dott. Costantino Pistagna <[email protected]> - BSD restrictions applies where possible DMI - Università di Catania - Dott. Costantino Pistagna <[email protected]> - BSD restrictions applies where possible Files Semplici ! I files piatti (o database hash) vengono utilizzati da altri programmi (server di posta, etc.) DB Relazionali ! In generale, I DB che parlano SQL sono relazionali. • Non scenderemo in dettaglio. Esiste un corso di DB! • Gnu DBM, Berkeley DB ! Forniscono il mezzo più leggero e veloce di archiviazione e di ricerca dei dati a coppie. ! La maggior parte dei DB usati con PHP è relazionale. • Username/Password, Messaggi/Utente, etc. ! Non creano da soli una rappresentazione di rapporti più complessi tra punti di dati. ! Useremo durante il corso un metodo comune di connessione a database relazionali. • Viene fatto dal programma client dell’utente. ! Dipende tutto dall’esperienza del programmatore. DMI - Università di Catania - Dott. Costantino Pistagna <[email protected]> - BSD restrictions applies where possible DMI - Università di Catania - Dott. Costantino Pistagna <[email protected]> - BSD restrictions applies where possible ODBC vs API Nativo ! Esistono due API generiche di accesso a DB: • Open DataBase Connectivity (ODBC) • Java DataBase Connectivity (JDBC) ! La prima è strettamente legata a microsoft. ! La seconda è ancora più strettamente legata a SUN. ! Altre aziende hanno implementato questi standard nei loro prodotti. ! ODBC e JDBC sono, in generale, mutuamente esclusivi. ODBC ! ODBC sia più lento delle API native • Ha il pregio di essere uno standard OPEN. ! Il codice scritto in PHP con ODBC funzionerà con qualunque DB che adotta lo standard ODBC! • E’ utile se vogliamo iniziare con un DB poco scalabile, per poi fare il ‘gran salto’!. • Esiste un collegamento ODBC-JDBC o Bridge per far comunicare I due. ! Molti DB hanno le proprie API native. • Più veloce che usare il sistema di ‘wrapping’ verdo *DBC. • La maggior parte dei DB OpenSource rientra in quest’ambito. DMI - Università di Catania - Dott. Costantino Pistagna <[email protected]> - BSD restrictions applies where possible DMI - Università di Catania - Dott. Costantino Pistagna <[email protected]> - BSD restrictions applies where possible Connesione a MySQL ! Il comando fondamentale per inizializzare una connessione a MySQL è: mysql_connect($nomehost, $utente, $password); ! La password è opzionale. • Dipende dal fatto che il particolare utente la richieda o meno. ! E’ anche possibile specificare porta e socket per il server • $nomehost:porta:socket Scegliere il DataBase ! Una volta aperta una connessione, si potrà scegliere il DB su cui lavorare. mysql_select_db($database); ! E’ necessario realizzare un DB ogni volta che si realizza una connessione. • Almeno una volta per pagina. • Quando si cambia DB. ! E’ necessario farlo anche se è stato creato un solo DB per utente. • MySQL ha dei DB predefiniti che potrebbero (o non si vorrebbe) prendere in considerazione. DMI - Università di Catania - Dott. Costantino Pistagna <[email protected]> - BSD restrictions applies where possible La nostra prima query ! Fondamentalmente una query a DB in PHP è un comando MySQL interito in una piccola funzione: • mysql_query(); ! Qui è dove vengono utilizzate le funzioni fondamentali di SQL (select, insert, update, delete). ! Con questa funzione è possibile anche creare / cancellare una tabella utilizzando le funzioni standard: • CREATE e DROP mysql_query(“SELECT Cognome FROM personali DMI - Università di Catania - Dott. Costantino Pistagna <[email protected]> - BSD restrictions applies where possible mysql_query() ! Ci sono buoni motivi per suddividere una query su due righe, facendo uso di variabili extra. ! Il motivo principale è che la variabile extra fornisce un sistema di identificazione di una parte di informazione estremamente preziosa. ! Ogni query MySQL fornisce una ricevuta si che vada a buon fine o no. ! Se si presenta un problema, la ricevuta fornirà un indizio essenziale per la corretta diagnostica del problema. WHERE ID < 10”); DMI - Università di Catania - Dott. Costantino Pistagna <[email protected]> - BSD restrictions applies where possible DMI - Università di Catania - Dott. Costantino Pistagna <[email protected]> - BSD restrictions applies where possible mysql_query() (2) Mysql_query() (3) ! mysql_query ha come argomenti <? mysql_query(“SELECT nome FROM dati WHERE ID < 10”); ?> <? $query = “SELECT nome FROM dati WHERE ID < 10”; $risultato = mysql_query($query); ?> DMI - Università di Catania - Dott. Costantino Pistagna <[email protected]> - BSD restrictions applies where possible mysql_query() (4) <? $query = “INSERT INTO dati (ID, nome) VALUES (NULL, ‘Elisa’)”; $risultato = mysql_query($query); if(!$risultato) { echo “c’è stato un errore!”; die(); } echo “righe affette: “ . mysql_affected_rows(); ?> • La stringa di query • Un identificatore di link opzionale ! A meno che non si abbiano più connessioni, l’identificatore di link non è necessario. ! Restituisce un valore TRUE intero se la query è andata a buon fine. FALSE altrimenti. ! Se la query era di tipo: insert, update, delete, create o drop table ed ha restituito TRUE • È possibile utilizzare mysql_affected_rows() per vedere quante righe sono state modificate dalla query. DMI - Università di Catania - Dott. Costantino Pistagna <[email protected]> - BSD restrictions applies where possible Mysql_query() (5) ! Se la query era una dichierazione SELECT, l’intero restituito ha un significato leggermente diverso: • Invece di TRUE o FALSE, restituisce un intero chiamato identificatore di risultato • E’ un identificatore univoco per ogni SELECT, in genere incrementato da 1. ! Con Select non è possibile utilizzare utilizzare la funzione mysql_affected_row() • E’ possibile, invece, utilizzare la funzione mysql_num_rows($risultato) "Ci ritorna il numero di righe che sono state restituite da SELECT. DMI - Università di Catania - Dott. Costantino Pistagna <[email protected]> - BSD restrictions applies where possible DMI - Università di Catania - Dott. Costantino Pistagna <[email protected]> - BSD restrictions applies where possible mysql_query() (6) <? mysql_connect(‘localhost’, ‘root’, ‘sesamo’); mysql_select_db(‘sampledb’); $query = “SELECT nome FROM dati WHERE ID < 10”; $risultato = mysql_query($query); echo “righe ritornate: “ . mysql_num_rows($risultato); ?> Ottenere un set di dati ! Sarebbe logico pensare che il risultato di una query sia il dato desiderato. • Sfortunatamente, non è corretto! ! Il risultato di una query PHP è un intero che rappresenta il successo, fallimento o l’identità della query. ! mysql_query() o mysql_db_query() estraggono i dati dal DB ed inviano a PHP una ricevuta che indica lo stato. ! Il dato, quindi, esiste in un purgatorio • Non accessibile nè da PHP, nè da MySQL. DMI - Università di Catania - Dott. Costantino Pistagna <[email protected]> - BSD restrictions applies where possible DMI - Università di Catania - Dott. Costantino Pistagna <[email protected]> - BSD restrictions applies where possible mysql_fetch() ! Per rendere il dato disponibile a PHP è necessaria una delle funzioni mysql_fetch(). ! Le funzioni per il recupero sono: • • • • Mysql_fetch_row() <? mysql_connect(‘localhost’, ‘root’, ‘sesamo’); mysql_select_db(‘sampledb’); $query = “SELECT ID, nome FROM dati WHERE ID < 10”; $risultato = mysql_query($query); echo “righe ritornate: “ . mysql_num_rows($risultato); mysql_fetch_row() - restituisce la riga come un array elenco. mysql_fetch_object() - restituisce la riga come un oggetto. mysql_fetch_array() “ “ “ array associativo. mysql_result() - restituisce una cella di dati. ! La più generale è mysql_fetch_row. DMI - Università di Catania - Dott. Costantino Pistagna <[email protected]> - BSD restrictions applies where possible while(list($ID, $nome) = mysql_fetch_row($risultato)) print(“$ID - $nome)<BR>\n”); die(); ?> DMI - Università di Catania - Dott. Costantino Pistagna <[email protected]> - BSD restrictions applies where possible Mysql_fetch_object <? mysql_connect(‘localhost’, ‘root’, ‘sesamo’); mysql_select_db(‘sampledb’); $query = “SELECT ID, nome FROM dati WHERE ID < 10”; $risultato = mysql_query($query); while($riga = mysql_fetch_object($risultato)) echo “$riga->ID” . “ - “ . “$riga->nome”; die(); ?> Mysql_fetch_array() ! La funzione di recupero più utile. ! Offre la scelta dei risultati come un array associativo o elenco (o entrambi, impostazione di default). ! E’ possibile fare riferimento agli output per nome di campo del DB anzichè per numero <? $query = “SELECT ID, nome FROM dati WHERE ID < 10”; $risultato = mysql_query($query); while($riga = mysql_fetch_array($risultato)) echo “$riga[ID] - $riga[nome]” . “<BR>\n”; die(); ! Ritorna a riga come un oggetto invece che come un array. ! Utile per I programmatori che usano la notazione di PHP orientata agli oggetti. ?> DMI - Università di Catania - Dott. Costantino Pistagna <[email protected]> - BSD restrictions applies where possible Mysql_fetch_array() (2) ! Può anche essere utilizzata esattamente allo stesso modo di mysql_fetch_row. • Con identificatori numerici, anzichè nomi di campo. ! Se si desidera specificare l’offset o il nome di campo, anzichè renderli entrami disponibili, si possono usare dei modificatori. <? //identificatore numerico $riga = mysql_fetch_array($risultato, MYSQL_NUM); DMI - Università di Catania - Dott. Costantino Pistagna <[email protected]> - BSD restrictions applies where possible Differenze prestazionali ! PHP3: mysql_fetch_row era considerata significativamente più veloce di mysql_fetch_object. • Non è più un problema! • PHP4 ha reso praticamente uguali le due. ! E’ consigliato usare mysql_fetch_array • Maggiori prestazioni. • Minori difficoltà implementative. • Maggiore facilità di manutenzione. //campo associativo $riga = mysql_fetch_array($risultato, MYSQL_ASSOC); ?> DMI - Università di Catania - Dott. Costantino Pistagna <[email protected]> - BSD restrictions applies where possible DMI - Università di Catania - Dott. Costantino Pistagna <[email protected]> - BSD restrictions applies where possible Mysql_result() ! Si dovrebbe utilizzare solo in situazioni in cui si è certi di avere bisogno della restituzione di un insieme ristretto di risultati. ! Prende tre argomenti: • L’identificatore di risultato. • L’identificatore di riga. • Il campo (opzionale). Mysql_result() (2) <? $query = “SELECT ID, nome FROM dati WHERE ID < 10”; $risultato = mysql_query($query); $datapoint = mysql_result($risultato, 0, 0); ?> "Può prendere il valore dell’offset di campo. "Il suo nome (come in un array associativo). "Il suo nome MySQL “campo punto tabella”. • Dove possibile utilizzare l’offset "E’ considerato il più veloce. DMI - Università di Catania - Dott. Costantino Pistagna <[email protected]> - BSD restrictions applies where possible DMI - Università di Catania - Dott. Costantino Pistagna <[email protected]> - BSD restrictions applies where possible Mysql_data_seek() ! Può essere utilizzata con una delle funzioni di recupero per designare in modo specifico il numero di riga desiderato. ! Prende come argomenti: Mysql_data_seek() (2) <? echo “<TABLE>\n<TR><TH>Titoli</TH></TR>\n<TR>”; $query = “SELECT * titolo, editore FROM libri”; $result = mysql_query($query); while($riga = mysql_fetch_array($result)) { echo “<TD>$riga[0]</TD>\n”; } echo “</TR></TABLE><BR>\n”; echo “<TABLE>\n<TR><TH>Editori</TH></TR>\n<TR>”; mysql_data_seek($result, 0); while($riga = mysql_fetch_array($result)) { echo “<TD>$riga[1]</TD>\n”; } echo “</TR></TABLE><BR>\n”; die(); • L’identificatore di risultato • Un numero di riga ! Sposta il puntatore interno di riga su quella specificata. ! L’utilizzo comune è lo scorrimento in un set di risultati dall’inizio, riportando il numero di riga a zero. • Simile al ripristino di un array. • Evita una dispendiosa chiamata al DB per ottenere dati che sono già nel lato PHP. DMI - Università di Catania - Dott. Costantino Pistagna <[email protected]> - BSD restrictions applies where possible ?> DMI - Università di Catania - Dott. Costantino Pistagna <[email protected]> - BSD restrictions applies where possible Le funzioni di metadati ! Le funzioni di metadati di MySQL ricadono in due categorie: • Funzioni che restituiscono informazioni solo sull’operazione precedente. • Funzioni che restituiscono informazioni sulla struttur adel DB. ! Per il primo tipo, ad esempio, mysql_insert_id(). • Restituisce l’ID autoincrementato assegnato ad una riga di dati appena inserita. ! La maggior parte di queste funzioni è efficace solo se viene usata nella combinazione adatta. • Non cercare di utilizzare mysql_affected_row() dopo una SELECT! ! Fare attenzione alla sicurezza con le funzioni che restituiscono informazioni sulla struttura del DB. • La conoscenza della struttura è un’informazione preziosa per un attacante! DMI - Università di Catania - Dott. Costantino Pistagna <[email protected]> - BSD restrictions applies where possible <? $query = “SELECT * titolo, editore FROM libri”; $result = mysql_query($query) or die(“controlla la query e riprova!”); while($riga = mysql_fetch_array($result)) { echo “<TD>$riga[0]</TD>\n”; } DMI - Università di Catania - Dott. Costantino Pistagna <[email protected]> - BSD restrictions applies where possible ! La funzione principale per il controllo di errori si chiama die(). ! PHP la elenca tra le funzioni miste. ! Fa semplicemente terminare lo script. • Restituendo una stringa scelta dal programmatore. … die(“controlla I dati inseriti!”); … ! E’ possibile integrare questa funzione con l’utilizzo di funzioni DB di PHP. DMI - Università di Catania - Dott. Costantino Pistagna <[email protected]> - BSD restrictions applies where possible Die() ?> Il controllo di errori Altri metodi per gli errori ! Gli altri sistemi per il controllo di errori sono I messaggi di errore. ! I messaggi di errore di MySQL non campaiono più per impostazione predefinita. ! Se si desidera averli è necessario richiederli: • mysql_errno() - restituisce un numero di codice per ogni tipo di errore. • mysql_error() - restituisce il testo del mex di errore. DMI - Università di Catania - Dott. Costantino Pistagna <[email protected]> - BSD restrictions applies where possible Creare DataBase con PHP ! Per creare un DB con PHP l’utente deve avere privilegi totali su MySQL. • Per CREATE e DROP. ! Chiunque trova gli scripts, può potenzialmente cancellare tutti I DB presenti sul server! ! La maggior parte dei servizi a pagamento non permetterà di farlo. Creare DataBase con PHP (2) ! Le funzioni più importanti per la creazione sono: • mysql_create_db() - crea un DB sull’host designato, con il nome specificato negli argomenti. • mysql_drop_db() - cancella il DB specificato. • mysql_query() - passa le definizioni delle tabelle. <? $IDLink = mysql_connect(‘localhost’,‘root’,‘sesamo’); mysql_create_db(‘nuovo_db’, $IDLink); mysql_select_db(‘nuovo_db’); $query = “CREATE TABLE new_tab (id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, new_col VARCHAR(25))”; $result = mysql_query($query); $kill_or_drunk = mysql_drop_db(‘nuovo_db’); ?> DMI - Università di Catania - Dott. Costantino Pistagna <[email protected]> - BSD restrictions applies where possible Cos’è una sessione? ! Ufficiosamente, una sessione di navigazione WEB è un periodo di tempo durante il quale una persona specifica vede pagine web. • Il sito web dell’hotel cariddi potrebbe avere una sessione durante la navigazione dell’utente all’interno della sua area riservata per il controllo dei dati anagrafici. ! Il protocollo HTTP è generico. • Non implementa particolari esigenze come quella delle sessioni. • E’ lasciato ai livelli superiori (come PHP) curarsi di queste esigenze. DMI - Università di Catania - Dott. Costantino Pistagna <[email protected]> - BSD restrictions applies where possible DMI - Università di Catania - Dott. Costantino Pistagna <[email protected]> - BSD restrictions applies where possible Perchè una sessione? ! Si vogliono personalizzare le esperienze degli utenti mentre si muovono nel sito. ! Si vogliono mostrare all’utente pubblicità, ma non lo si vuole fare più di una volta durante tutta la sessione. ! Si vuole che la sessione raccolga informazioni sulle azioni degli utenti (il carrello della spesa). ! Per tutti questi motivi è necessario essere in grado di accoppiare le richeiste di pagina con le sessioni di cui fanno parte. DMI - Università di Catania - Dott. Costantino Pistagna <[email protected]> - BSD restrictions applies where possible Come funzionano? ! Un buon supporto di sessione tiene cura di due cose: • Tenere traccia della sessione (quando due chiamate separate di script sono in realtà la stessa sessione). • Archiviare informazioni all’interno della sessione. ! Prima di PHP4 le sessioni erano gestite da un pacchetto esterno: PHPLIB • http://phplib.netuse.de Come funzionano? (2) ! Il tracciamento delle sessioni, avviene attraverso • Variabili nascoste • Cookies ! PHP utilizzerà I cookies quando il browser utente li supporta. ! Altrimenti farà ricorso a GET e POST. ! Le funzioni di sessione lavorano ad un livello più astratto. • Si preoccupano loro di questi dettagli. DMI - Università di Catania - Dott. Costantino Pistagna <[email protected]> - BSD restrictions applies where possible DMI - Università di Catania - Dott. Costantino Pistagna <[email protected]> - BSD restrictions applies where possible Session_start() ! PHP deve sapere se è in corso una sessione. • In questo modo può recuperare eventuali informazioni Session_register() ! Session_start() è una funzione complessiva. • Una sola chiamata rende disponibile tutte le variabili ! Session_register() è al dettaglio. ! session_start() (non prende argomenti). • E’ possibile utilizzare in maniera automatica session_start, impostando ad 1 il valore session.auto_start nel file php.ini. ! Qualsiasi chiamata a session_register() provocherà una chiamata implicita a session_start(). ! Se session_start trova una sessione, recupererà tutti i valori ereditati dalla sessione attuale rendendoli disponibili attraverso un array di sessione: $_SESSION. DMI - Università di Catania - Dott. Costantino Pistagna <[email protected]> - BSD restrictions applies where possible • Deve essere richiamata su ogni nuova variabile che si intende registrare. • Si preoccupa di rendere disponibile come variabile di sessione, la variabile passata come argomento. <? session_start(); session_register(‘mia_session’); ?> DMI - Università di Catania - Dott. Costantino Pistagna <[email protected]> - BSD restrictions applies where possible L’ambito super-globale ! Si può pensare alla registrazione di una variabile di sessione come una dichiarazione super-globale. Visualizzare $_SESSION <? session_start(); session_register(‘mia_session’); ?> ! Le variabili di funzione hanno ambito all’interno della funzione. ! Le variabili globali hanno ambito all’interno di un unico file di script. <? session_start(); echo “session var: “ . $_SESSION[‘mia_session’]; ?> ! Le variabili super-globali hanno ambito all’interno di tutta la sessione di lavoro. DMI - Università di Catania - Dott. Costantino Pistagna <[email protected]> - BSD restrictions applies where possible DMI - Università di Catania - Dott. Costantino Pistagna <[email protected]> - BSD restrictions applies where possible Session_unregister() ! Prende come argomento un nome di variabile stringa. ! Cancella la relativa variabile di sessione. ! La variabile non verrà più propagata alle pagine successive. Session_isregistered() ! Prende come argomento un nome di variabile stringa. ! Verifica l’esistenza della variabile all’interno della sessione. ! Restituisce TRUE in caso positivo. FALSE altrimenti <? <? session_start(); if(!session_isregistered(‘mia_session)) { session_register(‘mia_session’); } else { session_unregister(‘mia_session’); } session_start(); session_unregister(‘mia_session’); ?> ?> DMI - Università di Catania - Dott. Costantino Pistagna <[email protected]> - BSD restrictions applies where possible DMI - Università di Catania - Dott. Costantino Pistagna <[email protected]> - BSD restrictions applies where possible Session_destroy() ! Elimina la sessione corrente. ! Non cancella l’impostazione delle variabili per lo script corrente. <? session_start(); if(!session_isregistered(‘mia_session)) { session_register(‘mia_session’); } else { session_destroy(); } ?> Esercitazione 1 definire in PHP uno o piu' scripts che implementino: 1) il login sicuro in una zona del portale web. 2) la scrittura di un testo di dimensioni variabili all'interno del file *) ogni file che verra' referenziato dopo il login, deve tenere conto delle credenziali e verificarle ove necessario. **) il testo deve essere scritto utilizzando le funzioni preposte per le stringhe. Il nome del file de essere funzione della data odierna nell'ordine Anno/mese/giorno. Se il file esiste gia' deve essere riscritto. ***) non e' consentito l'uso di variabili globali e di sessione eccetto login e password. DMI - Università di Catania - Dott. Costantino Pistagna <[email protected]> - BSD restrictions applies where possible Esercitazione 2 realizzare uno script che date i seguenti dati: Stato | Capitale ---------------+--------------Alabama Montgomery Alaska Juneau Arizona Phoenix California Sacramento realizzi un form utente che permetta la scelta dello stato di cui visualizzare la capitale. *) si eviti l'uso di variabili globali e di sessione DMI - Università di Catania - Dott. Costantino Pistagna <[email protected]> - BSD restrictions applies where possible DMI - Università di Catania - Dott. Costantino Pistagna <[email protected]> - BSD restrictions applies where possible