9. Funzioni php di avanzate: database mysql Lezioni di web attivo 9. Accesso ai database mysql Per mostrare o modificare il contenuto della banca dati sul web è necessario realizzare pagine web attive server-side. Una pagina web attiva è una pagina che oltre alle normali tag HTML ingloba dei programmi che possono essere eseguiti dal browser (client-side) o dal web-server (server-side). Poichè le informazioni vive in questo caso risiedono sul server (gestite dal motore mysql) è necessario fare pagine attive server-side. Una pagina attiva server-side contiene (oltre alle tag HTML) programmi scritti in un linguaggio di scripting di tipo interpretato. Il web server prima di inviare al browser la pagina attiva richiesta la fa processare ad un interperter del linguaggio di scripting che esegue le istruzioni. Normalmente queste istruzioni consistono in un accesso alla banca dati per la estrazione delle informazioni vive e in una formattazione in HTML dei dati ottenuti. A questo punto il webserver invia al browser la pagina già formattata. In questo caso il linguaggio di scripting è Php installato come modulo del web-server Apache. Il modulo Php contiene anche la libreria di accesso a Mysql. La pagina deve essere identificata dal web-server come attiva mediante la sua estensione che quindi non deve essere .htm o .html ma .php oppure .php3 9.1 Connessione al database Il motore mysql si comporta come un server TCP. Quindi lo script php inglobato nella pagina attiva deve comportarsi come un client TCP attivando una connessione con il server. Al completamento della connessione Il client può iniziale il colloquio con il server, in primo luogo selezionando la banca dati con cui si vuole collegare e successivamente interrogando la banca dati con query SQL. Al termine dello script la connessione può essere chiusa, oppure si chiude automaticamente al completamento della interpretazione della pagina a meno che la connessione non sia stata dichiarata permanente. Il seguente esempio mostra la struttura tipica di una sequenza di connessione, che essendo di uso molto frequente può essere inserita in un file di inclusione e richiamata in tutti gli script che la richiedono. In ogni script che necessiti di una connessione ad una banca dati deve essere inserita prima di qualsiasi operazione sulla banca dati la seguente tag. ... <?php require(‘./include/connect.php’); ?> ... Note: La funzione require include nello script che la invoca lo script che ha per argomento entrandolo a far parte dello script principale nella posizione in cui si trova la funzione. Si potrebbe anche usare la funzione include; il vantaggio di require è che se l’inclusione fallisce anche lo script principale fallisce mentre nel caso della include lo script principale continua l’elaborazione. In sostanza si usa include quando un fallimento di inclusione non è fatale per lo script mentre require quando un fallimento è fatale. L’impossibilità di connettere è fatale per le successive query. Nell’esempio si ipotizza che lo script da includere si trovi in una cartella include contenuta nella cartella corrente. Lo script incluso si potrebbe presentare così: <?php // connessione $sock = mysql_connect("localhost","nobody",""); if ($sock==0) die(“Impossibile connettere a mysql”); $ris = mysql_select_db("prova",$sock); if ($ris==0) die(“Impossibile selezionare il database”); ?> ITIS “O.Belluzzi” – Laboratorio di Sistemi 1-17 9. Funzioni php di avanzate: database mysql Lezioni di web attivo Note: Uno script incluso deve riasserire le tag server side perché l’inclusione sospende l’interpretazione. Tutte le operazioni verso il motore mysql si fanno attraverso le funzioni della estensione mysql di php. Tutte le funzioni hanno un nome che inizia con mysql_… La funzione mysql_connect attiva una connessione client con il server mysql, specificando il nome host, il nome utente e la eventuale password. Se la connessione ha successo restituisce un identificativo che salvato nella variabile $sock consente il successivo utilizzo della connessione. Se restituisce 0 la connessione è fallita. In questo esempio la connessione è richiesta da nobody senza password. La sicurezza dell’accesso alla banca dati non è affidata all’accesso alla banca dati ma all’accesso allo script attraverso procedure di autenticazione che si vedranno nel prossimo capitolo. La funzione die termina l’interpretazione dello script e mostra un messaggio in output. Viene usata per bloccare lo script quando si verifica un errore fatale. La funzione mysql_select_db seleziona una particolare banca datt su una connessione attiva. Si specifica il nome della banca dati e l’identificativo della connessione. Se la selezione ha successo restituisce “true” Se lo script incluso non viene bloccato da un errore, la parte rimanente dell’script includente può usare la variabile $sock come identificatore di accesso alla connessione. 9.2 Selezione dei dati Dopo una connessione lo script ha la possibilità di accedere alle risorse dalla banca dati attraverso la connessione attiva. Per comprendere il meccanismo di accesso conviene considerare il più semplice tipo di operazione possibile, la selezione di una intera tabella. Selezionare una intera tabella vuole dire chiedere al motore di database di estrarre dal database una tabella e renderla disponibile come tabella dinamica attraverso un identificatore. Ottenuto l’identificatore di tabella, lo script lo percorre come se fosse un cursore fino a raggiungere la fine della tabella, ottenendo una dopo l’altra tutte le righe della tabella. Dal punto di vista del funzionamento quindi l’estrazione della tabella richiama l’operazione di lettura di un file sequenziale. Facendo riferimento alla semplice banca dati “prova” definita nel capitolo precedente e contentente la sola tabella “tab1” dotata di due colonne “id” e “dato” e popolati di dati: ... <table><tr><td>ID</td></tr><tr><td>Descrizione</td></tr> <?php $query=mysql_query(“select * from tab1”,$sock); if ($query) { while ($riga=mysql_fetch_assoc($query)) { ?> <tr> <td><?php echo($riga[‘id’]); ?></td> <td><?php echo($riga[‘dato’]); ?></td> </tr> <? } } else die(“errore di select”); ?> </tr></table> ... Note: La query viene realizzata con la funzione mysql_query che ha come parametri di ingresso il testo della query e l’identificatore di connessione. ITIS “O.Belluzzi” – Laboratorio di Sistemi 2-17 9. Funzioni php di avanzate: database mysql Lezioni di web attivo La funzione restituisce un identificatore, salvato in questo caso nella variabile $query che rappresenta il punto di accesso al risultato. Se la richiesta ha fallito, l’identificatore è nullo. Si deve tenere presente che il fallimento è cosa diversa dal numero di dati estratti. Quindi si può avere una query che ha avuto successo ma ha estratto nessun dato, perché nessun dato soddisfaceva alle condizioni richieste. In questo caso la query di selezione chiede la restituzione dell’intera tabella (* = tutte le colonne) senza alcuna condizione. La tabella non viene immediatamente restituita ma viene invece fornito un identificatore per i successivi accessi. Se l’identificatore è valido si può ottenere una riga della tabella mediante la funzione mysql_fetch_assoc che ha come parametro di ingresso l’identificatore di query e restituisce una array associativo che contiene la riga corrente della tabella. Ogni campo della riga è associato ad una posizione nell’array definita dal nome del campo. L’estrazione di una riga sposta avanti il cursore interno nella tabella quindi l’accesso successivo porta all’estrazione della riga successiva. Il raggiungimento della fine tabella porta alla restituzione di un NULL al posto dell’array e quindi alla chiusura del ciclo. L’output prodotto dallo script in questo esempio di mostra così: ... <table><tr><td>ID</td></tr><tr><td>Descrizione</td></tr> <tr><td>1</td><td>Pippo</td></tr> <tr><td>2</td><td>Pluto</td></tr> <tr><td>3</td><td>Topolino</td></tr> <tr><td>4</td><td>Minni</td></tr> </tr></table> Che corrisponde alla seguente presentazione: id 1 2 3 4 dato Pippo Pluto Topolino Minni ITIS “O.Belluzzi” – Laboratorio di Sistemi 3-17 9. Funzioni php di avanzate: database mysql Lezioni di web attivo 9.4 Operazioni di selezione sui database Note di carattere generale: Negli esempi che seguono vengono mostrate solo le stringe di selezione da usare nell’script php che vengono inserite nella variabile $msg da usare nella query. Le parole chiave del linguaggio SQL sono insensibili al caso (maiuscole/minuscole) I nomi tabella e i nomi campo sono insensibili al caso in ambiente win-32 ma sensibili al caso in ambiente linux I valori di tipo stringa utilizzati nelle query vengono inseriti come sono dal punto di vista del caso e sono insensibili al caso nei controlli (cioè inserire "mario" oppure "Mario" porta a contenuti diversi in bd ma la ricerca del valore "mario" o "Mario" ha successo in entrambi i casi (qualsiasi ambiente) Le stringhe vanno delimitate dal delimitatore di stringa (') mentre i valori numerici vanno inseriti senza delimitatori Il carattere singola quota (') è il delimitatore di stringa in SQL quindi per essere inserito in una stringa come apostrofo deve essere preceduto da un carattere di escape (\) esempio "\'" Il carattere barra rovescia (\) è il carattere di escape in SQL quindi per essere inserito in una stringa come barra diritta deve essere preceduto da un carattere di escape (\) esempio "\\" Il carattere $ è riconosciuto dall'interprete php come introduttore di variabile quindi per inserire in una stringa il carattere $ lo si deve fare precedere dal carattere di escape (\) esempio "\$" 9.4.1 Estrazione di tutti i campi di una tabella Corrisponde all’esempio già citato nel paragrafo precedente. ... $msg="SELECT * FROM tab"; ... Note: indica che devono essere estratti tutti i campi presenti nella tabella nell'ordine in cui sono presenti nel tracciato record della tabella. Tutti i record presenti in tabella sono estratti nell’ordine fisico in cui sono stati registrati Il numero di righe estratte può essere valutato a priori con la primitiva mysql_num_rows($query) che restituisce un intero 9.4.2 Estrazione di alcuni campi di una tabella Non sempre tutte le colonne di una tabella servono nella elaborazione, quindi per motivi di efficienza e di chiarezza si può limitare l’estrazioni ad alcune colonne. ... $msg="SELECT campo1,campo3 FROM tab"; ... Note: Le righe risultanti contengono solo due campi estratti dalla tabella per tutte le righe. Un errore nei nomi (anche il caso in linux) produce un NULL nel risultato $query che è diverso da ottenere un NULL estraendo la prima riga (in questo caso la query è corretta ma ha prodotto nessuna riga) ITIS “O.Belluzzi” – Laboratorio di Sistemi 4-17 9. Funzioni php di avanzate: database mysql Lezioni di web attivo 9.4.3 Estrazione di un particolare record usando la chiave primaria La query viene sottoposta ad una clausola where in cui si specifica un valore della chiave primaria. Poiché questo valore è univoco viene esttratta al massimo una riga. Negli esempi che seguono sono mostrate alcune possibili situazioni: ... $msg="SELECT $msg="SELECT $msg="SELECT $msg="SELECT $msg="SELECT $msg="SELECT ... * * * * * * FROM FROM FROM FROM FROM FROM tab tab tab tab tab tab WHERE WHERE WHERE WHERE WHERE WHERE ID_tab=5"; ID_tab=$prk"; ID_tab=".trim($prk); ID_tab='AB001'"; ID_tab='$prk'”; ID_tab='".addslashes($prk)."'"; supponendo che ID_tab sia il nome del campo chiave primaria della tabella i primi tre casi si riferiscono ad una chiave di tipo intero i secondi tre ad una chiave di tipo stringa; in tutti casi viene estratto al massimo un record, se esiste, che soddisfa al valore della chiave primaria. Note: Nel primo caso il valore numerico della chiave viene fornito come costante. Nel secondo caso il valore numerico della chiave viene fornito come variabile php annegata nella stringa sfruttando il fatto che l'interpreter php riconosce il simbolo $ come introduttore di variabile. Nel terzo caso non si è potuto sfruttare la possibilità di annegare la variabile nella stringa perché sulla variabile deve essere eseguita una funzione (trim rimuove eventuali cr ed lf presenti in fondo alla variabile che sono presenti nel caso in cui la variabile provenga da una gets fatta su un file di testo; non basta controllare per \n: ricordiamo che il web attivo è un ambiente multipiattaforma quindi non sappiamo da dove viene il file). In questo caso si usa l'operatore di concatenazione (.) Si deve ricordare che php è un processore di stringe quindi anche se per noi $prk è una variabile numerica in realtà è vista da php come una stringa numerica. Nel quarto caso il valore alfanumerico della chiave viene fornito come costante. Per fare riconoscere a mysql che è una stringa deve essere contornato da singole quote. N.B.: non si devono confondere le stringhe php con le stringe mysql; sono gestite da due motori diversi in cascata. Nel quinto caso il valore alfanumerico della chiave viene fornito come variabile php annegata nella stringa sfruttando il fatto che l'interpreter php riconsce il simbolo $ come introduttore di variabile. Anche in questo caso sono presenti le singole quote. Nel sesto caso non si è potuto sfruttare la possibilità di annegare la variabile nella stringa perché sulla variabile deve essere eseguita una funzione (addslashes aggiunge il carattere di escape (\) ai caratteri che lo richiedono come apici, dollari ecc …). In questo caso si usa due volte l'operatore di concatenazione (.) per innestare la funzione tra le due singole quote. 9.4.4 Estrazione di un gruppo di record usando condizioni sui campi La query viene sottoposta ad una clausola where in cui si specifica un range di valori che dono essere soddisfatti da uno o più campi. Negli esempi che seguono sono mostrate alcune possibili situazioni: ... $msg="SELECT $msg="SELECT $msg="SELECT $msg="SELECT ... * * * * FROM FROM FROM FROM tab tab tab tab WHERE WHERE WHERE WHERE nome='mario' nome='mario' cognome LIKE salario>1000 AND cognome='rossi"; OR cognome='rossi"; 'rossi%"; AND salario<2000; in questi casi vengono estratti tutti i record che soddisfano alle condizioni Note: ITIS “O.Belluzzi” – Laboratorio di Sistemi 5-17 9. Funzioni php di avanzate: database mysql Lezioni di web attivo Nel primo caso vengono estratti i record che contengono esattamente entrambi i valori (indipendentemente dal caso) Nel secondo caso vengono estratti i record che contengono esattamente uno oppure l'altro dei due valori. N.B. esistono molti altre combinazioni di operatori logici per cui si rimanda al manuale ufficiale di mysql. Nel terzo caso vengono estratti tutti i record che contengono il testo specificato perché % è una wildcard (quindi vengono estratti sia 'rossi' che 'rossini') Nel quarto caso vengono estratti tutti i record che in cui un campo numerico è contenuto in un certo range. 9.4.5 Ordinamento dei record Negli esempi precedenti l’ordinamento dei record era sempre quello fisico (ordine temporale di inserimento). In questo esempio i record vengono estratti ordinati con criterio alfanumerico sulla base del contenuto di alcuni campi. ... $msg="SELECT * FROM tab WHERE condizioni ORDER BY cognome,nome"; ... l'ordine in cui i record vengono presentati è determinato gerarchicamente dall'oridinamento del campo1 e nell'ambito dell'ordinamento del campo1 dall'ordinamento del campo2. Ad esempio: Note: L’ordinamento è lessicografico e segue l’ordine delle codifiche ASCII dei simboli. Di conseguenza i numeri e i caratteri speciali precedono le lettere maiuscole e minuscole. Ad esempio: 10A precede sia AB che 2A. L’ordinamento gerarchico fa si che vengano ordinato prima il campo cognome e poi nell’ambito del cognome viene oridnato il campo nome. 9.4.6 Estrazione dei dati da una associazione 1:N Negli esempi trattati fino ad ora i dati erano estratti sempre da un’unica tabella. E’ spesso necessario unire più tabelle in un join per creare nuove tabelle che pongono in relazione dati di tabelle diverse. Questa operazione si realizza mediante il prodotto cartesiano tra tabelle che si ottiene mettendo nella clausola FROM più di una tabella ed effettuando una restrizione mediante le clausole WHERE ... $msg="SELECT t1.campo1, t2.campo2 FROM tab1 as t1, tab2 as t2 WHERE t1.extk=t2.prk"; ... supponendo che tab1 sia la tabella dal lato N e tab2 la tabella dal lato 1 la query estrae una tabella virtuale composta dal campo1 di tab1 e dal campo2 di tab2 relativo alla riga di tab2 correlata mediante chiave esterna alla riga di tab1 Esempio: tab1 contiene i comuni italiani con chiave esterna verso le provincie, 1,'Castenaso',1 2,'Bologna', 1 3,'Sassuolo', 2 … tab2 contiene le provincie italiane, ITIS “O.Belluzzi” – Laboratorio di Sistemi 6-17 9. Funzioni php di avanzate: database mysql Lezioni di web attivo 1,'BO' 2,'MO' … nella tabella dei comuni compare per ciascun comune, come chiave esterna, la chiave primaria della provincia a cui il comune appartiene. La tabella risultante contiene in ogni riga il campo1 del comune (ad esempio il nome) ed il campo2 della provincia a cui il comune appartiene (ad esempio la sigla) 'Castenaso',' BO' 'Bologna', 'BO' 'Sassuolo', 'MO' Note: E' possibile spezzare le righe per migliorare la leggibilità Poiché i campi provengono da più tabelle origine è necessario specificare la tabella di provenienza di ciascun campo. E' preferibile associare ad ogni tabella un alias t1 per tab1 e t2 per tab2 e riferirsi al nome alias anziché al nome vero della tabella (Questa modalità è indispensabile in caso di join interno ad una stessa tabella) Nel WHERE può essere aggiunta ogni altra condizione per modificare il range della tabella risultante Può essere aggiunta la clausola ORDER BY che in questo caso deve specificare anche l'alias. 9.4.7 Estrazione dei dati da una associazione N:M Nel caso in cui l’associazione sia N:M nel modello relazionale le tabelle diventano tre. E’ necessario effettuare il prodotto cartesiano delle tre tabelle ed effettuare la restrizione usando le due chiavi esterne. ... $msg="SELECT t1.campo1, t2.campo2 FROM tab1 as t1, tab2 as t2, tab3 as t3 WHERE t3.prk1=t1.prk AND t3.prk2=t2.prk "; ... supponendo che tab3 sia la tabella di associazione, tab1 e tab2 siano le tabelle associate query estrae una tabella virtuale composta dal campo1 di tab1 e dal campo2 di tab2. Esistono tante righe quante sono le associazioni valide tra i record di tab1 ed i record di tab2 Esempio: tab1 contiene i libri di una biblioteca 1,'titolo1' 2,'titolo2' 3,'titolo3' tab2 contiene gli autori dei libri 1,'autore1' 2,'autore2' tab3 contiene le associazioni tra autori e libri; ogni riga è composta da una coppia di chiavi di libro e autore che indica che un autore ha scritto (o ha partecipato alla scrittura se la chiave libro non è univoca in tab3) di un certo libro, oppure vedendo l'associazione dall'altro lato che un libro è stato scritto da un autore o da più autori (se la chiave autore non è univoca in tab3 in associazione a quel libro) Esempio: ITIS “O.Belluzzi” – Laboratorio di Sistemi 7-17 9. Funzioni php di avanzate: database mysql 1,1 -> titolo1 è 1,2 -> titolo1 è 2,1 -> titolo2 è 3,2 -> titolo3 è Il risultato della query è: 'Titolo1','Autore1' 'Titolo1','Autore2' 'Titolo2','Autore1' 'Titolo3','Autore2' stato stato stato stato scritto scritto scritto scritto Lezioni di web attivo da autore1 anche da autore2 da autore1 da autore2 Alcune varianti: ... $msg="SELECT t1.campo1, t2.campo2 FROM tab1 as t1, tab2 as t2, tab3 as t3 WHERE t3.prk1=t1.prk AND t3.prk2=t2.prk AND t1.prk=valore"; ... Estrae solo le righe relative ad un particolare valore della associazione Si può applicare nell'esempio precedente per estrarre: Tutti i libri scritti da un certo autore Tutti gli autori che hanno scritto un certo libro 9.4.8 Conteggio dei record aventi una determinata proprietà Questa funzione consente di raggruppare valori omogenei che si trovano sulla stessa colonna. ... $msg = "SELECT t1.campo1, ..., COUNT(t1.campo1) AS c1 FROM tab1 AS t1, ... WHERE Condizioni GROUP BY t1.campo1 ORDER BY c1 DESC"; ... Note: L'esempio si riferisce al caso molto comune in cui la tabella su cui si fa il conteggio sia ottenuta da una query su una relazione per i dattagli riferirsi a casi precedenti. Tra i campi deve essere presente il campo su cui si vuole fare il conteggio (per avere l'etichetta) ed un campo COUNT riferito al campo da contare per avere il valore associato ad un alias in modo da potere fare l'ordinamento ITIS “O.Belluzzi” – Laboratorio di Sistemi 8-17 9. Funzioni php di avanzate: database mysql Lezioni di web attivo La clausola GROUP BY deve essere riferita al campo dotato di conteggio La clausola ORDER BY ordina secondo il contatore (riferito come alias) in ordine decrescente Se la tabella tab1 è cosi composta: 1,'dato1' 2,'dato2' 3,'dato1' 4,'dato3' 5,'dato1' 6,'dato3' il risultato è: 'dato1',3 'dato3',2 'dato2',1 9.5 Operazioni di inserimento nei database Le operazioni di inserimento aggiungono un nuovo record ad una tabella. Dal punto di vista del web attivo sono generalmente inserite in uno script organizzato come una automa a stati finiti. Nel suo stato iniziale lo script presenta una form i cui campi modulo sono inizializzati al valore vuoto o ad un particolare valore di default richiesto dal problema. Il submit della form, come già visto nel capitolo sulle pagine come automa, verifica (client side) la validità dei dati proposti, cambia il valore della variabile di stato e rilancia se stessa. Al secondo lancio dello script, lo stato modificato provoca l’azione di inserimento. A questo punto si possono avere due situazioni diverse in funzione del tipo di chiave primaria: Chiave artificiale ad autoincremento: l’insieme dei dati proposti, già verificati client side, viene inserito nella tabella senza ulteriori verifiche, viene controllato il successo dell’inserimento e poi viene estratta prima la chiave primaria autogenerata e poi l’intero record per presentare il risultato della operazione. Chiave naturale: viene verificata la NON-ESISTENZA della chiave primaria proposta e solo in questo caso l’insieme dei dati proposti, già verificati client side, viene inserito nella tabella senza ulteriori verifiche, viene controllato il successo dell’inserimento e poi viene estratto l’intero record per presentare il risultato della operazione. ITIS “O.Belluzzi” – Laboratorio di Sistemi 9-17 9. Funzioni php di avanzate: database mysql Lezioni di web attivo Nel primo caso lo script si presenta in questo modo: ... <?php if (!isset($stato)) $stato=”V”; //lo stato di default è visualizzazione if (!isset($campo1)) $campo1=””; if (!isset($campo2)) $campo2=””; if (!isset($campo2)) $campo2=””; require(‘./include/connect.php’); ?> ... <script language=”javascript”> function vailda(form) { // ... controllo validità form.stato.value=”I”; //aggiorna stato futuro return true; } </script> ... <?php if ($stato==”I”) { //stato di inserimento $msg=”INSERT INTO tab (campo2,campo3) VALUES ($campo2,$campo3)”; $query=mysql_query($msg,$sock); //inserisce nuovo record $msg=”SELECT LAST_INSERT_ID()”; $query=mysql_query($msg,$sock); //estrae id ultimo inserito $riga=mysql_fetch_row($query); $campo1=$riga[0]; $msg=”SELECT * FROM tab WHERE campo1=$campo1; $query=mysql_query($msg,$sock); //estre dati appena inseriti $riga=mysql_fetch_assoc($query); $campo1=$riga[‘campo1’]; $campo2=$riga[‘campo2’]; $campo3=$riga[‘campo3’]; } ?> ... <form action=”<?php echo”$PHP_SELF” ?>” onsubmit=”return valida(this)> <input type=”hidden” name=”stato” value=”<?php echo $stato ?>” > <input type=”text” name=”campo1” value=”<?php echo $campo1 ?>” readonly> <input type=”text” name=”campo2” value=”<?php echo $campo2 ?>” > <input type=”text” name=”campo3” value=”<?php echo $campo3 ?>” > <input type=”submit” name=”submit1” value=”inserisci”> </form> ... Note: Nell’esempio sono riportate solo le parti essenziali della parte statica trascurando gli elementi che, pur indispensabili per una corretta presentazione, sono ininfluenti dal punto di vista del problema dell’inserimento Nello script di inserimento sono stati omessi, per semplicità di presentazioni, tutti i controlli sui risultati delle funzioni di database che invece vanno verificati per presentare una corretta via di fuga da eventuali errori di sistema. Al primo avvio la pagina si pone in stato “V” e quindi salta tutte le operazioni di inserimento, inoltre inizializza i campi modulo ai valori di default. ITIS “O.Belluzzi” – Laboratorio di Sistemi 10-17 9. Funzioni php di avanzate: database mysql Lezioni di web attivo Alla sottomissione viene eseguito lo script client side valida() che dopo aver controllato la validità dei dati (codice omesso) modifica la variabile di stato al valore “I” e rilancia la pagina stessa ($PHP_SELF) Al successivo rilancio la variabile di stato vale “I” e quindi viene eseguito il ramo di inserimento che, se tutto procede in modo corretto carica i valori inseriti nella variabili presentate nei campi modulo. I valori vengono inseriti nella tabella omettendo il campo chiave che si genera automaticamente con il primo intero libero in tabella. Se l’inserimento ha successo si estrae la chiave autogenerata con la funzione mysql LAST_INSERT_ID(). Usando questa chiave come clausola si estrae l’intero record. In questo modo i campi modulo contengo i valori EFFETTIVAMENTE inseriti e non i valori proposti. Il campo modulo della chiave primaria è dichiarato READ ONLY per evitare modifiche che non potrebbero avere successo. ITIS “O.Belluzzi” – Laboratorio di Sistemi 11-17 9. Funzioni php di avanzate: database mysql Lezioni di web attivo Mentre nel secondo caso si presenta così: ... <?php if (!isset($stato) $stato=”V”; //lo stato di default è visualizzazione if (!isset($campo1) $campo1=””; if (!isset($campo2) $campo2=””; if (!isset($campo2) $campo2=””; require(‘./include/connect.php’); ?> ... <script language=”javascript”> function vailda(form) { // ... controllo validità form.stato.value=”I”; //aggiorna stato futuro return true; } </script> ... <?php if ($stato==”I”) //stato di inserimento $msg=”SELECT * FROM tab WHERE campo1=$campo1”; $query=mysql_query($msg,$sock); //cerca il record di chiave campo1 $nrec=mysql_num_row($query); if ($nerc==0) { //se non esiste inserisce $msg=”INSERT INTO tab (campo1,campo2,campo3) VALUES ($campo1,$campo2,$campo3)”; $query=mysql_query($msg,$sock); //inserisce nuovo record $msg=”SELECT * FROM tab WHERE campo1=$campo1; $query=mysql_query($msg,$sock); //estre dati appena inseriti $riga=mysql_fect_assoc($query); $campo1=$riga[‘campo1’]; $campo2=$riga[‘campo2’]; $campo3=$riga[‘campo3’]; } else die(“errore il record esiste”); } ?> ... <form action=”<?php echo”$PHP_SELF” ?>” onsubmit=”return valida(this)> <input type=”hidden” name=”stato” value=”<?php echo $stato ?>” > <input type=”text” name=”campo1” value=”<?php echo $campo1 ?>” readonly> <input type=”text” name=”campo2” value=”<?php echo $campo2 ?>” > <input type=”text” name=”campo3” value=”<?php echo $campo3 ?>” > <input type=”submit” name=”submit1” value=”inserisci”> </form> ... Note: Nell’esempio sono riportate solo le parti essenziali della parte statica trascurando gli elementi che, pur indispensabili per una corretta presentazione, sono ininfluenti dal punto di vista del problema dell’inserimento ITIS “O.Belluzzi” – Laboratorio di Sistemi 12-17 9. Funzioni php di avanzate: database mysql Lezioni di web attivo Nello script di inserimento sono stati omessi, per semplicità di presentazioni, tutti i controlli sui risultati delle funzioni di database che invece vanno verificati per presentare una corretta via di fuga da eventuali errori di sistema. Al primo avvio la pagina si pone in stato “V” e quindi salta tutte le operazioni di inserimento, inoltre inizializza i campi modulo ai valori di default. Alla sottomissione viene eseguito lo script client side valida() che dopo aver controllato la validità dei dati (codice omesso) modifica la variabile di stato al valore “I” e rilancia la pagina stessa ($PHP_SELF) Al successivo rilancio la variabile di stato vale “I” e quindi viene eseguito il ramo di inserimento che, se tutto procede in modo corretto carica i valori inseriti nella variabili presentate nei campi modulo. Prima di inserire viene cercata l’eventuale presenza della chiave primaria in tabella Se la chiave esiste giù non si può fare l’inserimento Se l’inserimento ha successo si estrae il record usando la chiave come clausola. In questo modo i campi modulo contengo i valori EFFETTIVAMENTE inseriti e non i valori proposti. Il campo modulo della chiave primaria è dichiarato READ ONLY per evitare modifiche. Non si può mai cambiare il campo chiave perché diventerebbe un altro record. 9.6 Operazioni di modifica nei database Le operazioni di modifica operano su record già esistente in una tabella. Il primo problema la identificazione del record da modificare. Per questa operazione preliminare in genere si usa una normale pagina di selezione che mostra tutti i record esistenti in una tabella. Ciascun record viene reso attivo mediante un collegamento alla vera e propria pagina di modifica che viene quindi lanciata ricevendo come parametro di get la chiave primaria del record da modificare. Pagina di selezione: ... <table><tr><td>ID</td></tr><tr><td>Descrizione</td></tr> <?php $query=mysql_query(“select * from tab”,$sock); if ($query) { while ($riga=mysql_fetch_assoc($query)) { ?> <tr> <td><a href=”modifica.php?id?<?php echo($riga[‘id’]) ?>”> <?php echo($riga[‘id’]); ?> </a> </td> <td><?php echo($riga[‘dato’]); ?></td> </tr> <? } } else die(“errore di select”); ?> </tr></table> ... Note: La pagina corrisponde alla pagina di selezione dell’esempio del punto 9.2 salvo per la presenza delle ancore in corrispondenza delle chiavi primarie. Per ogni record estratto in corrispondenza della chiave primaria viene generato un link (ancora) verso la pagina di modifica che contiene come parametro di get il valore della chiave primaria. L’output prodotto dallo script in questo esempio di mostra così: ITIS “O.Belluzzi” – Laboratorio di Sistemi 13-17 9. Funzioni php di avanzate: database mysql Lezioni di web attivo ... <table><tr><td>ID</td></tr><tr><td>Descrizione</td></tr> <tr><td><a href=modifica.php?id=1>1</a></td><td>Pippo</td></tr> <tr><td><a href=modifica.php?id=2>2</a></td><td>Pluto</td></tr> <tr><td><a href=modifica.php?id=3>3</a></td><td>Topolino</td></tr> <tr><td><a href=modifica.php?id=4>4</a></td><td>Minni</td></tr> </tr></table> ... Che corrisponde alla seguente presentazione: id 1 2 3 4 dato Pippo Pluto Topolino Minni La pagina di modifica non differisce sostanzialmente dalla pagina di inserimento salvo per il fatto che si aspetta di trovare in ingresso una chiave primaria valida su cui fare la query per estrarre i dati esistenti da sottoporre a modifica. Realizzata sotto forma di automa stati finiti, quando rilancia se stessa in modifica effettua un update del record e mostra i risultati della modifica. ITIS “O.Belluzzi” – Laboratorio di Sistemi 14-17 9. Funzioni php di avanzate: database mysql Lezioni di web attivo ... <?php if (!isset($stato) $stato=”V”; //lo stato di default è visualizzazione if (!isset($campo1)) die(“manca la chiave primaria”); if (!isset($campo2)) $campo2=””; if (!isset($campo2)) $campo2=””; require(‘./include/connect.php’); ?> ... <script language=”javascript”> function vailda(form) { // ... controllo validità form.stato.value==”M”; //aggiorna stato futuro return true; } </script> ... <?php if ($stato=”M” //stato di inserimento $msg=”UPDATE tab SET campo2=$campo2,campo3=$campo3 WHERE campo1=$campo1”; $query=mysql_query($msg,$sock); //modifica il record } $msg=”SELECT * FROM tab WHERE campo1=$campo1”; $query=mysql_query($msg,$sock); //estrae il record modif. o da modif. $riga=mysql_fetch_assoc($query); $campo1=$riga[‘campo1’]; $campo2=$riga[‘campo2’]; $campo3=$riga[‘campo3’]; ?> ... <form action=”<?php echo”$PHP_SELF” ?>” onsubmit=”return valida(this)> <input type=”hidden” name=”stato” value=”<?php echo $stato ?>” > <input type=”text” name=”campo1” value=”<?php echo $campo1 ?>” readonly> <input type=”text” name=”campo2” value=”<?php echo $campo2 ?>” > <input type=”text” name=”campo3” value=”<?php echo $campo3 ?>” > <input type=”submit” name=”submit” value=”modifica”> </form> ... Note: Nell’esempio sono riportate solo le parti essenziali della parte statica trascurando gli elementi che, pur indispensabili per una corretta presentazione, sono ininfluenti dal punto di vista del problema dell’inserimento Nello script di inserimento sono stati omessi, per semplicità di presentazioni, tutti i controlli sui risultati delle funzioni di database che invece vanno verificati per presentare una corretta via di fuga da eventuali errori di sistema. Al primo avvio la pagina si pone in stato “V” e quindi salta tutte le operazioni di modifica ma effettua le operazioni di selezione, inoltre inizializza i campi modulo ai valori di default. Alla sottomissione viene eseguito lo script client side valida() che dopo aver controllato la validità dei dati (codice omesso) modifica la variabile di stato al valore “M” e rilancia la pagina stessa ($PHP_SELF) Al successivo rilancio la variabile di stato vale “M” e quindi viene eseguito il ramo di modifica che aggiorna il contenuto della banca dati. Successivamente il codice di selezione, che non è sottoposto a condizioni, viene eseguito estraendo i dati modificati che quindi sono ora disponibili per una verifica e/o una ulteriore modifica. Non ci sono differenza tra chiavi naturali ed artificiali ad autoincremento. 9.7 Operazioni di cancellazione nei database ITIS “O.Belluzzi” – Laboratorio di Sistemi 15-17 9. Funzioni php di avanzate: database mysql Lezioni di web attivo Le operazioni di cancellazione operano su record già esistente in una tabella. Il primo problema la identificazione del record da cancellare. Per questa operazione preliminare in genere si usa una normale pagina di selezione che mostra tutti i record esistenti in una tabella. Ciascun record viene reso attivo mediante un collegamento alla vera e propria pagina di modifica che viene quindi lanciata ricevendo come parametro di get la chiave primaria del record da modificare. La pagina di selezione è uguale alla pagina di selezione per modifica già presentata. La pagina di cancellazione non differisce sostanzialmente dalla pagina di modifica. Infatti prima di effettuare una vera e propria cancellazione è opportuno presentare i dati nel loro complesso per consentire una valutazione della effettiva cancellazione. L’unica differenza consiste nel fatto che tutti i campi sono READ ONLY. Realizzata sotto forma di automa stati finiti, quando rilancia se stessa in cancellazione effettua una cancellazione del record e mostra i risultati della cancellazione. ... <?php if (!isset($stato)) $stato=”V”; //lo stato di default è visualizzazione if (!isset($campo1)) die(“manca la chiave primaria”); if (!isset($campo2)) $campo2=””; if (!isset($campo2)) $campo2=””; require(‘./include/connect.php’); ?> ... <script language=”javascript”> function vailda(form) { // ... controllo validità form.stato.value=”C”; //aggiorna stato futuro return true; } </script> ... <?php if ($stato==”C”) //stato di inserimento $msg=”DELETE FROM tab WHERE campo1=$campo1”; $query=mysql_query($msg,$sock); //cancella il record } $msg=”SELECT * FROM tab WHERE campo1=$campo1”; $query=mysql_query($msg,$sock); //estrae il record canc. o da canca. $riga=mysql_fetch_assoc($query); if ($riga) { $campo1=$riga[‘campo1’]; $campo2=$riga[‘campo2’]; $campo3=$riga[‘campo3’]; } ?> ... <form action=”<?php echo”$PHP_SELF” ?>” onsubmit=”return valida(this)> <input type=”hidden” name=”stato” value=”<?php echo $stato ?>” > <input type=”text” name=”campo1” value=”<?php echo $campo1 ?>” readonly> <input type=”text” name=”campo2” value=”<?php echo $campo2 ?>” > <input type=”text” name=”campo3” value=”<?php echo $campo3 ?>” > <input type=”submit” name=”submit” value=”modifica”> </form> ... Note: ITIS “O.Belluzzi” – Laboratorio di Sistemi 16-17 9. Funzioni php di avanzate: database mysql Lezioni di web attivo Nell’esempio sono riportate solo le parti essenziali della parte statica trascurando gli elementi che, pur indispensabili per una corretta presentazione, sono ininfluenti dal punto di vista del problema dell’inserimento Nello script di inserimento sono stati omessi, per semplicità di presentazioni, tutti i controlli sui risultati delle funzioni di database che invece vanno verificati per presentare una corretta via di fuga da eventuali errori di sistema. Al primo avvio la pagina si pone in stato “V” e quindi salta tutte le operazioni di modifica ma effettua le operazioni di selezione, inoltre inizializza i campi modulo ai valori di default. Alla sottomissione viene eseguito lo script client side valida() che dopo aver controllato la validità dei dati (codice omesso) modifica la variabile di stato al valore “M” e rilancia la pagina stessa ($PHP_SELF) Al successivo rilancio la variabile di stato vale “M” e quindi viene eseguito il ramo di modifica che aggiorna il contenuto della banca dati. Successivamente il codice di selezione, che non è sottoposto a condizioni, viene eseguito estraendo i dati modificati che quindi sono ora disponibili per una verifica e/o una ulteriore modifica. Non ci sono differenza tra chiavi naturali ed artificiali ad autoincremento. ITIS “O.Belluzzi” – Laboratorio di Sistemi 17-17