[successivo] [precedente] [inizio] [fine] [indice generale] [indice ridotto] [translators] [docinfo] [indice analitico] [volume] [parte]


Capitolo 300.   Il PHP e le base di dati

Una caratteristica del PHP è la capacità di gestire direttamente i principali serventi di base di dati tramite connessioni dirette senza l'utilizzo di strati intermedi quali ODBC (anche se gestiti perfettamente) o JDBC; una volta installato l'interprete in modo corretto, si è in grado di connettersi a qualunque base di dati(1). Si va da ORACLE a MSSQLServer a DB2 per arrivare ai più diffusi e leggeri MySQL e PostgreSQL.

La scelta di MySQL per gli esempi della guida non è casuale bensì obbligata visto il successo avuto negli ultimi anni da questo DBMS(2) che vanta una leggerezza e grandi prestazioni anche se non dispone di tutte le caratteristiche e funzionalità dei concorrenti di fascia superiore. Inoltre è distribuito liberamente in Internet ed è facile da installare e configurare.

Per lo sviluppo di progetti di medie dimensioni, dunque, MySQL risulta un'ottima scelta; per questo motivo i siti Internet che lo utilizzano aumentano a vista d'occhio incoraggiandone lo sviluppo.

Tutto ciò che verrà trattato di seguito con applicazioni pratiche riguarderà MySQL.

300.1   Gestione centralizzata della base di dati

Il PHP è in grado di gestire le base di dati mediante un linguaggio d'interrogazione strutturato chiamato SQL(3) che tramite una sintassi standard permette di effettuare tutte le operazioni necessarie sui dati contenuti in archivio, inserimenti, modifiche, cancellazioni, selezione e quanto altro. Verrà data per scontata una conoscenza di base dell'SQL e si procederà con la trattazione di problematiche legate al suo utilizzo tramite il PHP.

Le base di dati sono strutture progettate e realizzate con lo scopo di immagazzinare e gestire grandi moli di dati. Mediante particolari algoritmi di ricerca vengono forniti i dati richiesti in breve tempo senza doversi preoccupare di come essi vengono scritti e letti sul disco, in altre parole si può pensare alla base di dati come ad un magazzino al quale ci si rivolge per depositare e ritirare del materiale senza doversi preoccupare di dove e come esso viene archiviato. Nel momento del bisogno basterà solo richiedere il materiale al "magazziniere" che saprà dove e come prendere i dati e come fornirceli in maniera leggibile.

Una volta creata la base di dati e attivate le politiche di accesso ciò di cui si necessita per operare sui dati è:

Appare chiaro che questi dati sono importanti e vanno tenuti segreti ma è altrettanto chiaro che potrebbero cambiare per motivi di sicurezza o per necessità di manutenzione; tale aspetto non va sottovalutato durante la progettazione e la scrittura del codice. Un consiglio è quello di concentrare in un unico file tutti i parametri necessari alla connessione alla base di dati, tale file verrà poi incluso all'inizio di ogni pagina dalla quale si voglia effettuare una connessione al database.

In una situazione estrema potrebbe cambiare addirittura il tipo di DBMS utilizzato, in questo caso se si rispettano gli standard e si disegna il codice in modo intelligente con poche modifiche si può continuare ad utilizzare la stessa applicazione PHP pur cambiando il tipo di base di dati in gioco. Questo tuttavia è un esempio estremo e se non si hanno necessità particolari(4) di progettazione conviene disegnare l'applicazione intorno alla base di dati in modo da sfruttare al massimo le prestazioni del DBMS.

Un buon metodo di procedere è quello di inserire uno strato tra le funzioni del PHP e la nostra programmazione, ad esempio una classe che gestisce l'interazione con la base di dati, in questo modo il codice è meno rigido e permette di apportare modifiche in modo meno laborioso.

Un esempio pratico. Le fasi principali di una interrogazione ad una base di dati sono le seguenti:

   Connessione alla base di dati

      interrogazione 1
      interrogazione 2
      ...
      interrogazione n

   Disconnessione dalla base di dati

Osserviamo nel dettaglio la gestione della connessione ad una base dati nel caso di MySQL:

0 <?
1  $host = "192.168.1.1";
2  $user = "utente_autorizzato";
3  $password = "password_utente";
4 
5  $connessione = mysql_connect($host,$user,$password);
6 
7  mysql_close($connessione);
8 ?>

Mentre nel caso di PostgreSQL:

0  <?
1   $port = 5432;           # numero di porta in cui ascolta PostgreSQL
2   $host = "192.168.1.1";
3   $user = "utente_autorizzato";
4   $password = "password_utente";
5   $dbname = "nome_base_dati";
6   $authtype="password"    # tipo di autenticazione
7 
8   $connessione = pg_Connect("$host $port $dbname $user $password $authtype");
9 
10  pg_Close($connessione);
11 ?>

Le differenze sono lampanti, PostgreSQL richiede molti parametri in più, inoltre effettua una connessione direttamente ad una particolare base di dati mentre in MySQL il nome del database va specificato al momento dell'esecuzione della query SQL.

Si pensi ad un sito moderno con molti contenuti, ad esempio un portale che in ogni pagina esegue almeno una connessione per estrarre i dati da visualizzare dalla base di dati; è impensabile scrivere codice come quello visto sopra in ogni pagina del sito, se solo cambiasse la password si dovrebbero modificare tutte le pagine interessate.

A questo punto dovrebbe essere chiaro che l'ideale è la realizzazione di una classe da includere all'inizio di ogni pagina PHP che necessita di una connessione alla base di dati, in cui implementare tutte le funzionalità necessarie.

I problemi precedentemente posti sono risolti. Se dovessero cambiare i parametri basterebbe modificare un solo file, quello contenente la dichiarazione della classe, impostando i nuovi valori. Se dovesse cambiare il DBMS basterebbe riscrivere il codice della classe mantenendo invariati gli standard di definizione e funzionamento dei metodi, in questo modo tutti gli oggetti continuerebbero a funzionare. Non sempre questo passaggio è possibile, tutto dipende da come viene scritto il codice.

Nelle pagine seguenti verrà implementata una classe utile per la gestione di base di dati MySQL dando per scontata la procedura di creazione della base di dati utilizzata negli esempi che seguiranno la parte teorica.

Per gli esempi pratici della guida verrà utilizzata una piccola e semplice base di dati dal nome brdp_esempio_1 il cui script di creazione è reperibile al seguente indirizzo in formato.tgz: <http://www.urcanet.it/brdp/php_manual/esempi/cap_8/sql_1.tgz> o se si preferisce il formato .zip: <http://www.urcanet.it/brdp/php_manual/esempi/cap_8/sql_1.zip>

300.2   La classe database

In questa sezione verrà trattata la classe database, distribuita sotto licenza GNU/GPL, che gestisce la connessione e l'interazione con le base di dati, in questo caso di tipo MySQL ma un utile esercizio potrebbe essere la riscrittura della classe per un altro DBMS, ad esempio PostgreSQL.

La versione completa della classe può essere scaricata nei formati .tgz e .zip dai seguenti indirizzi: <http://www.urcanet.it/brdp/php_manual/esempi/cap_8/brdp_db_php.tgz> e <http://www.urcanet.it/brdp/php_manual/esempi/cap_8/brdp_db.zip>

Ecco un estratto del codice della classe.

1  <?
2  
3  class database {
4    var $db;
5  
6  
7  /*
8  @@@@@@@@@@@@@@@@@@@@@@@@@@|  COSTRUTTORE  |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
9   assegna i valori alla variabile $db per poi aprire la connessione
10  mediante il metodo connetti(); se al momento della dich. dell'oggetto non
11  vengono passati valori specifici vengono assegnati i valori di default
12 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
13 */
14   function database($USER="brdp", $PASSWORD="brdp", $DB="brdp_esempio_1", 
      $HOST="localhost" ){
15      $this->db["user"] = $USER;
16      $this->db["password"] = $PASSWORD;
17      $this->db["db"] = $DB;
18      $this->db["host"] = $HOST;
19   }
20 
21 
22 /*
23 #############################|  METODO  |###################################
24  Apre la connessione al DB secondo i valori impostati dal costruttore.
25  Se la connessione fallisce visualizza un messaggio di errore.
26  La parte HTML può essere personalizzata secondo le necessitá
27 ############################################################################
28 */
29   function connetti(){
30     $this->db["connessione"] = @mysql_connect($this->db[host],
        $this->db[user],$this->db[password]);
31     if ($this->db[connessione]){
32       return $this->db[connessione];
33     }else{
34       # La tabella seguente contiene il messaggio di errore di
35       # connessione. può essere personalizzato secondo le necessità.
36 ?>
37     <br>
38     <table align="center" width="500" cellspacing="0" cellpadding="4"
        border="1">
39       <tr bgcolor="#e2e2e2">
40         <td>
41           <font color="#000000" face="helvetica,verdana" size="5">
42            <b>PROBLEMI DI CONNESSIONE</b>
43           </font>
44         </td>
45       </tr>
46       <tr>
47         <td>
48           <font size="2" color="#4F4F4F" face="Helvetica, Verdana">
49             I nostri server sono, momentaneamente, <b>sovraccarichi</b>
50             e NON possono stabilire una connessione. Vi invitiamo a 
51             riprovare più tardi. Se il problema persiste, per favore,
52             segnalatelo al<b><i>
53             <a href="mailto:webmastert@del_sito.it">webmaster</a></i></b>.
54           </font>
55         </td>
56       </tr>
57     </table>
58 <?
59         exit;
60     }
61   }
62
63 
64 /*
65 #############################|  METODO  |###################################
66  Chiude la connessione al DB aperta dal metodo connetti();
67 
68 
69 ############################################################################
70 */
71   function disconnetti(){
72     @mysql_close($this->db[connessione]);
73   }
74 
75 
76 /*
77 #############################|  METODO  |###################################
78  Esegue la query ricevuta come parametro alla chiamata.
79  Se la query e la sua esecuzione vanno a buon fine ritorna true o il
80  risultato (esempio in una select) altrimenti torna false
81 ############################################################################
82 */
83   function esegui($query){
84     $this->db["risultato"] = @mysql_db_query($this->db[db], $query,
        $this->db[connessione]);
85     return $this->db[risultato];
86   }
87 
88 
89 /*
90 #############################|  METODO  |###################################
91  Esegue la query ricevuta come parametro alla chiamata formatta il
92  risultato in una select html. Va passata la query, il campo da visualizz.
93  il valore da inserire in value il valore del selected e il tipo di output
94 ############################################################################
95 */
96   function query2select($query, $nome, $valore, $default, $metodo){
97     if($this->esegui($query)){
98       for($i=0; $i<$this->righe(); $i++){
99         $sel="";
100         if ($default == $this->leggi($i,$valore))
101           $sel="selected";
102 
103         $ris = $ris."<option value=\"".$this->leggi($i,$valore)."\" ".$sel.">";
104         $ris = $ris.$this->leggi($i,$nome)."</option>\n";
105       }
106 
107       if($metodo){
108         echo $ris;
109         return true;
110       }else{
111         return $ris;
112       }
113     }else{
114       return false;
115     }
116   }
117
118 
119 /*
120 #############################|  METODO  |###################################
121  Nel caso di una query di insert torna il valore dell'ID se auto_increment
122  assegnato all'ultimo valore inserito nel DB da questa connessione.
123  NON l'ultimo in assoluto! l'ultimo inserito tramite questa connessione!
124 ############################################################################
125 */
126   function getlast_id(){
127     return @mysql_insert_id($this->db[connessione]);
128   }
129 
130 
131 /*
132 #############################|  METODO  |###################################
133  Ritorna il valore del campo $nome_campo della riga $numero_riga
134  restituito da una query tipo select
135 
136 ############################################################################
137 */
138   function leggi($numero_riga,$nome_campo){
139     return @mysql_result($this->db[risultato],$numero_riga,$nome_campo);
140   }
141 
142 
143 /*
144 #############################|  METODO  |###################################
145  Ritorna il numero di righe restituito dall'ultima query di tipo select
146 
147 
148 ############################################################################
149 */
150   function righe(){
151     $this->db["righe"] = @mysql_num_rows($this->db[risultato]);
152     return $this->db[righe];
153   }
154 }
155 
156 ?>

Si inizi con l'analizzare la struttura della classe. Il costruttore ammette quattro parametri, ovvero i parametri necessari alla connessione con la base di dati; essi possono essere scritti in modo diretto nella classe o impostati in altri file di configurazione da includere prima di essa. Nei nostri esempi inseriremo i parametri nella classe e la includeremo come libreria al principio di ogni script che necessita di interfacciarsi con una base di dati.

Dal modo in cui vengono passati i parametri al costruttore si capisce che la classe gestirà una base di dati di default ma sarà in grado di interrogarne anche altre tramite oggetti dichiarati con parametri diversi. Per comprendere meglio il concetto ecco un esempio:

<?
   include("brdp_db.php");

   # Oggetto per la gestione della Base dati di default
   $db_1 = new database;
   
   # Oggetto per la gestione di una Base dati occasionale o diversa
   $db_2 = new database("utente_xxx", "passwd", "DB_di_prova", "localhost");
   
?>

I due oggetti creati lavoreranno in modo analogo con gli stessi metodi ma su due base di dati diverse, tuttavia conviene dichiarare sempre i parametri in modo centralizzato, magari in un array prima della classe, in questo modo sarà sempre semplice modificare i valori necessari alla connessione.

Una volta creato l'oggetto bisogna connettersi al DBMS; va sottolineato che l'accesso alla base di dati è di tipo concorrenziale e che c'è un limite alle connessioni che possono essere mantenute aperte contemporaneamente dal servente, quindi è bene chiudere sempre la connessione e prima possibile.

<?
   include("brdp_db.php");

   # Creazione oggetto
   $db = new database;
   
   # Apertura della connessione
   $db->connetti();

   # Chiusura della connessione
   $db->disconnetti();
 ?>

Come è facile intuire, con il metodo connetti() viene aperta la connessione che può essere chiusa tramite il metodo disconnetti(). Se il DBMS è in ascolto e i parametri per la connessione, nonchè la base di dati, sono corretti l'esempio dovrebbe mostrare una schermata bianca, in caso contrario una pagina simile a quella in figura 300.7.

Figura 300.7. Il messaggio può essere personalizzato nella dichiarazione della classe. Notare che i messaggi di errori dell'interprete non compaiono.

figure/brdp_noconnessione

Dunque una volta connessi è possibile interrogare la base di dati mediante la sintassi SQL e il metodo esegui($query_sql) che ritorna un valore falso se ci sono problemi durante l'esecuzione della query.

In particolare il PHP restituisce il risultato di operazioni di tipo SELECT in array associativi a due dimensioni strutturati con il nome del campo e il numero di righe partendo da 0. In pratica, una query di questo genere: SELECT nome, cognome FROM BRDP_TB_UTENTI LIMIT 0, 3 eseguita sulla base di dati di prova brdp_esempio_1 restituisce questo risultato:

+----------+---------+
| nome     | cognome |
+----------+---------+
| Gianluca | Giusti  |
| Mirko    | Simeoni |
| Fabio    | Ferri   |
+----------+---------+

Viene estratto sotto forma di array associativo di dimensione 2x3 i cui valori possono essere "letti" tramite il metodo leggi($numero_riga,$nome_campo). Per conoscere il numero di righe restituite dalla query basta utilizzare il metodo righe(). Ricapitolando la procedura è la seguente:

1   <?
2     include("brdp_db.php");
3 
4     # Creazione oggetto
5     $db = new database;
6    
7     # Apertura della connessione
8     $db->connetti();
9 
10    # Preaparazione della Query
11    $query_sql = "SELECT nome, cognome FROM BRDP_TB_UTENTI LIMIT 0, 3";
12
13    if($db->esegui($query_sql)){
14       for($i=0; $i<$db->righe(); $i++ ){
15         echo "<br>".$i.") Nome: ".$db->leggi($i,"nome");
16       }
17    }
18    
19    # Chiusura della connessione
20    $db->disconnetti();
21  ?>

Il risultato è simile a:

0) Nome: Gianluca
1) Nome: Mirko
2) Nome: Fabio

Va notato che lo script non mostra il cognome, è compito del lettore completare l'esempio.

Una volta creato l'oggetto e stabilita la connessione viene impostata la query da eseguire sulla base di dati, tramite un controllo if ne viene verificata l'esecuzione, se non è falsa allora cicla i valori estratti tramite un ciclo for. Per la precisione andrebbe inserito un else alla riga 17 per segnalare eventuali errori nell'esecuzione, anche questo ultimo ritocco è lasciato come esercizio al lettore.

Va sottolineato che le righe dell'array partono con indice 0.

Per concludere, la classe comprende altri due metodi query2select e getlast_id che verranno trattati in seguito tramite degli esempi. Il primo esegue una query e formatta il risultato nel contenuto di una SELECT HTML mentre il secondo restituisce il valore dell'ID generato (in modalità "auto_increment") nell'ultimo inserimento effettuato tramite la connessione in uso dall'oggetto.

300.3   Primo esempio di utilizzo della classe database

Per gli esempi di utilizzo della classe verrà utilizzata la base di dati chiamata brdp_esempio_1 che è possibile riprodurre fedelmente tramite lo script reperibile all'indirizzo riportato nella sezione 300.1.

La base di dati è molto semplice ed è composta da due tabelle strutturate come di seguito:

BRDP_TB_UTENTI
+-----------+--------------+------+-----+---------+----------------+
| Field     | Type         | Null | Key | Default | Extra          |
+-----------+--------------+------+-----+---------+----------------+
| id_utente | int(11)      |      | PRI | NULL    | auto_increment |
| nome      | varchar(70)  |      |     |         |                |
| cognome   | varchar(70)  |      |     |         |                |
| email     | varchar(100) |      |     |         |                |
| attivo    | int(11)      |      |     | 0       |                |
+-----------+--------------+------+-----+---------+----------------+


BRDP_TB_AGENDA
+-----------+--------------+------+-----+---------+----------------+
| Field     | Type         | Null | Key | Default | Extra          |
+-----------+--------------+------+-----+---------+----------------+
| id_agenda | int(11)      |      | PRI | NULL    | auto_increment |
| id_utente | int(11)      |      |     | 0       |                |
| Nome      | varchar(70)  |      |     |         |                |
| Cognome   | varchar(70)  |      |     |         |                |
| email     | varchar(100) |      |     |         |                |
| telefono  | varchar(20)  |      |     |         |                |
| fax       | varchar(20)  |      |     |         |                |
+-----------+--------------+------+-----+---------+----------------+

La prima BRDP_TB_UTENTI contiene i dati relativi a degli utenti fittizi che potrebbero avere a disposizione la possibilità di gestire una loro rubrica, mentre BRDP_TB_AGENDA contiene i contatti degli utenti relazionati tramite il valore BRDP_TB_AGENDA.id_utente all'utenza BRDP_TB_UTENTI.id_utente. La struttura è molto semplice e serve solo come appoggio per gli script di esempio inquanto la complessità delle query in gioco non cambia il concetto.

Come primo passo nel file index.php raggiungibile a questo indirizzo: <http://www.urcanet.it/brdp/php_manual/esempi/cap_8/index.php> viene eseguita una semplice query che restituisce tutti gli utenti con campo attivo = 1. Spesso si preferisce non rimuovere fisicamente, dati non sensibili, dalla base di dati ma eliminarli logicamente ovvero tramite un campo convenzionalmente impostato a zero. In questo caso il campo che discrimina l'esistenza o meno dell'utente è il campo "attivo", se contiene valore pari a 0 l'utente non è attivo, se è 1 allora va visualizzato in elenco.

di seguito il codice del primo esempio:

1  <?
2    # Includo la classe per la gestione della base di dati
3    include("brdp_db.php");
4
5    $db = new database;
6    $db->connetti();
7    $sql = "SELECT * from BRDP_TB_UTENTI where attivo=1";
8  ?>
9
10 <html>
11 <head>
12   <title>Primo esempio di connessione alla base di dati</title>
13 </head>
14 <body>
15
16 <br>
17 [
18  <a href="../../">HOME</a> -
19  <a href="../">ESEMPI</a>
20 ]
21
22 <br><br>
23 Esempio di <b>interrogazione di base di dati</b>.
24 <br><br>
25
26 Come prima cosa viene effettuata una semplice SELECT dalla
27 tabella <b>BRDP_TB_UTENTI</b> selezionando solo gli utenti attivi.
28 La Query da eseguire è la seguente:
29
30 <br><br>
31   <i><?=$sql?></i>
32 <br><br>
33
34 Questo il risultato della query:
35 <br><br>
36
37 <table>
38 <?
39  # Eseguo la query contenuta in $sql
40  if($db->esegui($sql)){
41    if($db->righe()>0){
42      for($i=0; $i<$db->righe(); $i++){
43        $j=$i+1;
44        echo "<tr><td>".$j.") ".$db->leggi($i,"nome")."</td>";
45        echo "<td><a href=\"dettagli.php?utente=";
46        echo $db->leggi($i,"id_utente")."\">Dettagli utente</a></td>";
47        echo "<td><a href=\"agenda.php?utente=".$db->leggi($i,"id_utente");
48        echo "&nome=".$db->leggi($i,"nome");
49        echo "\">Agenda utente</a></td></tr>";
50      }
51    }else{
52      echo "<tr><td>Nessun utente attivo in archivio</td></tr>";
53    }
54  }else{
55    echo "<tr><td>Errore di interrogazione.</td></tr>";
56  }
57 ?>
58 </table>
59
60 </body>
61 </html>
62
63 <?
64   # chiusura della connessione alla base dati è importante!
65   $db->disconnetti();
66 ?>

Come prima cosa alla riga 3 viene inclusa la classe di gestione della base di dati, da tale riga in poi sarà possibile istanziare oggetti di tipo database ed usarne tutti i metodi.

Alla riga 5 viene creata l'istanza $db alla classe database. Di seguito alla riga 6 il primo utilizzo del nuovo oggetto con l'apertura della connessione alla base di dati predefinita. Come visto precedentemente questo è il passo che permette in caso di necessità di specificare parametri di connessione diversi da quelli predefiniti e impostati nella classe di connessione nel file brdp_db.php.

Nella riga 7 viene assegnata alla variabile $sql la query come una semplice stringa, questa variabile sarà poi fornita al metodo di esecuzione.

Segue del semplice codice HTML mentre alla riga 31 viene mostrata la query che verrà eseguita in fase di interrogazione.

Prima di approfondire la parte più interessante dell'esempio è bene ricordare l'importanza della gestione degli errori. In questo caso la query è statica dunque una volta testatone il funzionamente non si dovrebbero avere problemi inquanto non cambierà nel tempo, spesso però tali stringhe vengono composte usando parametri ricevuti da altre pagine e questo aumenta le probabilità di errore dovuti a eccezioni non gestite. La classe in ogni caso nasconde ogni tipo di errore dell'interprete PHP ma per realizzare un codice professionale non basta, bisogna anche informare il visitatore di cosa sta succedendo o comunque informarlo della generazione di un errore.

L'esecuzione della query avviene alla riga 40 ed avviene all'interno di un'istruzione if, questo perchè il metodo torna un valore falso in caso di errore e di conseguenza mostra al visitatore il messaggio della riga 55.

Se la query viene eseguita senza errori l'interprete continua con l'esecuzione della riga 41. Nell'esempio in oggetto viene eseguita una SELECT dunque il risultato sarà un array associativo con 5 colonne ed n righe. A priori non si conosce il numero di voci restituite dalla query per questo, alla riga 41, prima di visualizzare le voci viene controllata la quantità di righe tramite il metodo righe(), se è zero viene informato il visitatore che non sono state trovate voci in archivio altrimenti viene mostrato il risultato.

Dalla riga 42 alla 50 viene visualizzato il risultato della SELECT mediante un ciclo for. È importante notare come si parta dal valore 0 e si incrementi $db->righe() volte.

I valori vengono visualizzati mediante il metodo leggi() che accetta il numero di riga da leggere e il nome della colonna (campo della tabella) da estrarre. Il funzionamento è semplice e intuitivo, e si può trattare il metodo come una semplice variabile ad esempio leggendo l'i-esimo nome come di seguito:

  # assegnazione ad una variabile
  $nome = $db->leggi($i,"nome");

  # visualizzazione diretta dell'i-esimo nome
  echo $db->leggi($i,"nome");

  # Concatenazione con una stringa
  echo "Ecco il nome del fortunato: ".$db->leggi($i,"nome");

  # utilizzo con funzioni predefinite
  echo "tolgo gli eventuali spazi a destra: ".rtrim($db->leggi($i,"nome"));

Mentre si visualizza il risultato vengono costruiti dinamicamente i collegamenti alle pagine di dettaglio e agenda relative all'utente in oggetto. Il risultato dello script è riportato in figura 300.14.

Figura 300.14. L'elenco utenti e i collegamenti vengono creati dinamicamente in seguito all'interrogazione della base di dati.

figure/brdp_db_select_1

300.4   Il metodo query2select

Nella programmazione di tutti i giorni si ripetono molte operazioni: una, ad esempio, è la realizzazione di una lista partendo dai dati contenuti in una o più tabelle di una base di dati. Il metodo query2select permette di formattare i dati ottenuti tramite una SELECT SQL in una SELECT HTML. Il risultato è mostrato in figura 300.16.

Il codice per ottenere tale risultato è il seguente:

1  <?
2    # Includo la classe per la gestione della base di dati
3    include("brdp_db.php");
4
5    $db = new database;
6    $db->connetti();
7
8    $sql = "select * from BRDP_TB_AGENDA where id_utente=".$HTTP_GET_VARS["utente"];
9  ?>
10
11 <html>
12 <head>
13   <title>Agenda utenti</title>
14 </head>
15 <body>
16
17 <br>
18 [
19  <a href="../../">HOME</a> -
20  <a href="../">ESEMPI</a> -
21  <a href="index.php">Inizio ESEMPIO</a>
22 ]
23 <br><br>
24 Esempio di <b>interrogazione di base di dati</b>.
25 <br><br>
26 Viene eseguita una SELECT sulla tabella <b>BRDP_TB_AGENDA</b>
27 per visualizzare i contatti relativi all'utente con id_utente pari al
28 parametro passato con il nome di "utente".
29 La Query da eseguire è la seguente:
30 <br><br>
31   <i><?=$sql?></i>
32 <br><br>
33 Questo il risultato della query tramite il metodo <b><i>query2select</i></b>:
34 <br><br>
35
36 <form method="get" action="contatto.php" name="dettagli_contatto">
37   ecco i contatti dell'utente <b><?=$HTTP_GET_VARS["nome"]?></b>: &nbsp;
38   <select name="contatto">
39 <?
40   $db->query2select($sql,"nome","id_agenda",false,true);
41 ?>
42 </select> &nbsp;
43 <input type="submit" value="mostra dettagli">
44 </form>
45
46 </body>
47 </html>
48
49
50 <?
51   # chiusura della connessione alla base dati è importante!
52   $db->disconnetti();
53 ?>

Il codice è molto simile all'esempio precedente, quindi non necessita di particolari spiegazioni. La parte da analizzare è la riga 40 dove viene utilizzato il metodo in analisi; i parametri da passare sono cinque: la stringa contenente la SELECT SQL, il campo da mostrare nella SELECT HTML (in questo caso nome), il campo da impostare come valore dell'attributo value della scelta HTML. Il metodo inoltre accetta un eventuale valore da impostare come selezionato se trovato tra i valori estratti dalla base di dati (se falso allora nessun valore sarà selezionato). Infine si trova il metodo di risposta, ovvero il modo in cui il risultato deve essere restituito; se il parametro è vero mostra a video i dati estratti e formattati, altrimenti se è falso li ritorna come valore.

Figura 300.16. Il metodo query2select esegue la query e restituisce direttamente valori in una SELECT HTML.

figure/brdp_db_select_3

Analizzando il sorgente della pagina visualizzata sul navigatore si capisce meglio il funzionamento e l'utilizzo dei parametri passati al metodo. Questo è ciò che viene generato dal metodo:

 <form method="get" action="contatto.php" name="dettagli_contatto">
   ecco i contatti dell'utente <b>Gianluca</b>: &nbsp;
   <select name="contatto">
     <option value="1" >Bianchi</option>
     <option value="2" >Rossi</option>
     <option value="5" >Francesco</option>
   </select> &nbsp;
   <input type="submit" value="mostra dettagli">
 </form>

Se la riga 40 fosse stata questa:

40   $db->query2select($sql,"nome","id_agenda","Rossi",true);

il risultato ottenuto sarebbe stato:

 <form method="get" action="contatto.php" name="dettagli_contatto">
   ecco i contatti dell'utente <b>Gianluca</b>: &nbsp;
   <select name="contatto">
     <option value="1" >Bianchi</option>
     <option value="2" selected>Rossi</option>
     <option value="5" >Francesco</option>
   </select> &nbsp;
   <input type="submit" value="mostra dettagli">
 </form>

Ovvero l'utente "Rossi" sarebbe stato impostato come selezionato, questo risulta comodo nelle maschere di modifica dove esiste già un valore da visualizzare come predefinito.

300.5   Costruzione dinamica delle query

Come anticipato nei capitoli precedenti le query possono essere composte dinamicamente utilizzando il PHP.

I collegamenti realizzati nel precedente esempio forniscono tramite il metodo get uno o più parametri alle pagine di destinazione. Si prenda in considerazione lo script dettagli.php che riceve il parametro utente. Tale pagina effettuerà una SELECT nella tabella BRDP_TB_UTENTI della base di dati estraendo i dati relativi all'utente con id_utente uguale al valore ricevuto in get da index.php. Con il codice seguente si otterrà il risultato mostrato in figura 300.21.

1  <?
2    # Includo la classe per la gestione della base di dati
3    include("brdp_db.php");
4
5    $db = new database;
6    $db->connetti();
7
8    $sql = "SELECT * from BRDP_TB_UTENTI where id_utente=".$HTTP_GET_VARS["utente"];
9  ?>
10
11 <html>
12 <head>
13   <title>Dettagli utente</title>
14 </head>
15 <body>
16
17 <br>
18 [
19  <a href="../../">HOME</a> -
20  <a href="../">ESEMPI</a> -
21  <a href="index.php">Inizio ESEMPIO</a>
22 ]
23 <br><br>
24 Esempio di <b>interrogazione di base di dati</b>.
25 <br><br>
26 Viene eseguita una SELECT sulla tabella <b>BRDP_TB_UTENTI</b>
27 per visualizzare i dettagli dell'utente con id_utente pari al 
28 parametro passato con il nome di "utente".
29 La Query da eseguire è la seguente:
30 <br><br>
31   <i><?=$sql?></i>
32 <br><br>
33 Questo il risultato della query:
34 <br><br>
35
36 <table>
37 <?
38  # eseguo la query
39  if($db->esegui($sql)){
40    if($db->righe()==1){
41      echo "<tr><td>Codice:</td> <td>".$db->leggi(0,"id_utente")."</td></tr>";
42      echo "<tr><td>Nome:</td> <td>".$db->leggi(0,"nome")."</td></tr>";
43      echo "<tr><td>Cognome:</td> <td>".$db->leggi(0,"cognome")."</td></tr>";
44      echo "<tr><td>e-mail:</td> <td>".$db->leggi(0,"email")."</td></tr>";
45      echo "<tr><td></td> <td><a href=\"agenda.php?utente=";
46      echo $db->leggi($i,"id_utente")."&nome=".$db->leggi(0,"nome")."\">Agenda utente</a>
        </td></tr>";
47    }else{
48      echo "<tr><td>Nessun utente attivo in archivio con questo codice</td></tr>";
49    }
50  }else{
51    echo "<tr><td>Errore di interrogazione.</td></tr>";
52  }
53 ?>
54 </table>
55 
56 </body>
57 </html>
58 
59 
60 <?
61   # chiusura della connessione alla base dati è importante!
62   $db->disconnetti();
63 ?>

Oltre a cambiare il modo di formattazione del risultato, varia la costruzione della query; questa volta, infatti, viene assemblata usando un parametro ricevuto da un'altra pagina. Nell'esempio non vengono effettuati controlli sul valore di tale variabile, ma in circostanze più serie è buona norma verificare almeno il tipo di dato e se la variabile è nulla. Ad esempio, in questo caso ci si aspetta un valore intero (il codice utente). Il controllo viene lasciato come esercizio al lettore.

Nell'esempio la query è molto semplice ma spesso ci si trova ad operare con strutture più complesse e con vari parametri da filtrare per ogni interrogazione; in queste situazioni è importante gestire tutte le possibili eccezioni in modo da eliminare eventuali errori.

Figura 300.21. Con la condizione where viene selezionato un solo utente. La query viene generata dinamicamente.

figure/brdp_db_select_2

In questo caso il risultato considerato corretto deve fornire una sola, riga dunque il controllo è quello della riga 41 oltre al solito sull'esecuzione alla riga 40.

Inoltre, essendo una sola riga non si ha bisogno di ciclare l'array; di conseguenza al metodo leggi() viene passato direttamente il valore 0 pari alla prima riga.

300.6   Altri tipi di query

Come più volte sottolineato, questa non vuole essere una guida sull'SQL; tuttavia non esiste il solo comando SELECT ma è possibile inserire, aggiornare e rimuovere dei valori dalla base di dati, oltre a svariate altre operazioni che esulano dall'obiettivo di questa guida e che quindi non verranno trattate.

Di seguito verrà osservato il comportamento del PHP nel gestire istruzioni che non restituiscono dei valori, come nel caso del comando SELECT, ma che restituiscono un valore falso se qualcosa è andato storto.

Prima di analizzare il codice è bene ricordare che è di fondamentale importanza la gestione di eventuali errori e dei messaggi restituiti dal DBMS.

Si supponga di aver ricevuto dei dati da un modulo HTML e di voler inserire tali informazioni nella tabella dei contatti BRDP_TB_AGENDA. I dati da gestire sono: nome, cognome, email, telefono, fax e utente. Va ricordato che la tabella in oggetto è relazionata alla tabella BRDP_TB_UTENTI dunque la nuova riga che si andrà ad inserire dovrà in qualche modo riferirsi ad un utente contenuto nella tabella degli utenti. Il dato che permette di mantenere tale relazione è passato dal modulo con la variabile utente, che dunque deve essere un intero.

Questa è la porzione di codice che gestisce l'inserimento:

<?
# Includo la classe per la gestione della base di dati
include("brdp_db.php");

$db = new database;
$db->connetti();

  $sql =  " INSERT
              into BRDP_TB_AGENDA
                (
                  id_utente,
                  nome,
                  cognome,
                  email,
                  telefono,
                  fax
                ) values (
                   ".$HTTP_GET_VARS["utente"].",
                  '".$HTTP_GET_VARS["nome"]."',
                  '".$HTTP_GET_VARS["cognome"]."',
                  '".$HTTP_GET_VARS["email"]."',
                  '".$HTTP_GET_VARS["tel"]."',
                  '".$HTTP_GET_VARS["fax"]."'
                )
          ";

  if($db->esegui($sql)){
    echo "Inserimento eseguito.";
  }else{
    echo "Problemi durante l'inserimento.";
  }

# chiusura della connessione alla base dati è importante!
$db->disconnetti();
?>

Va notato come i valori di tipo non numerico vadano racchiusi tra il singolo apice, mentre, i numerici possono essere passati direttamente.

L'indentazione della query non è obbligatoria, ma in casi di interrogazioni complesse aiuta ad individuare eventuali errori in fase di correzione: dunque è consigliata.

Il funzionamento del comando UPDATE è simile all'inserimento e permette di modificare uno o più campi di una tabella tramite le condizioni della clausula WHERE.

Di seguito un esempio di una porzione di codice SQL che gestisce un aggiornamento.

<?
# Includo la classe per la gestione della base di dati
include("brdp_db.php");

$db = new database;
$db->connetti();

  $sql = " update
               BRDP_TB_AGENDA
           set
               Nome = '".$HTTP_GET_VARS["nome"]."' ,
               Cognome = '".$HTTP_GET_VARS["cognome"]."' ,
               email = '".$HTTP_GET_VARS["email"]."' ,
               telefono = '".$HTTP_GET_VARS["tel"]."' ,
               fax = '".$HTTP_GET_VARS["fax"]."'
           where
               id_agenda = ".$HTTP_GET_VARS["contatto"]."
         ";

  if($db->esegui($sql)){
    echo "Modifica completata eseguito.";
  }else{
    echo "Problemi durante la modifica.";
  }

# chiusura della connessione alla base dati è importante!
$db->disconnetti();
?>

Come è facile notare, la gestione della query dal punto di vista dell'interprete PHP è del tutto identica alla INSERT ed alla DELETE che viene riportata di seguito.

<?
# Includo la classe per la gestione della base di dati
include("brdp_db.php");

$db = new database;
$db->connetti();

  $sql = " delete from
               BRDP_TB_AGENDA
           where
               id_agenda = ".$HTTP_GET_VARS["contatto"]."
         ";

  if($db->esegui($sql)){
    echo "Modifica completata eseguito.";
  }else{
    echo "Problemi durante la modifica.";
  }

# chiusura della connessione alla base dati è importante!
$db->disconnetti();
?>

Nelle operazioni di cancellazione e modifica è importante ponderare le condizioni altrimenti tutti i campi verranno interessati. Ad esempio, una query come: delete from BRDP_TB_AGENDA svuota la tabella BRDP_TB_AGENDA di tutto il suo contenuto.

A seguito di un'interrogazione è possibile ottenere informazioni più dettagliate, come il numero di righe interessate dall'operazione, o ancora gestire i singoli tipi di errori del DBMS. Per quanto interessante, questo aspetto esula dallo scopo della guida ma rimane un ottimo esercizio per quanti vogliano approfondire l'argomento.

300.7   Applicazioni pratiche, gestione di una rubrica

Come esempio nei capitoli precedenti si è trattata la gestione di una semplice agenda multiutente; di seguito essa verrà completata in modo da aumentare la dimestichezza con gli argomenti fin qui trattati.

Nella directory contenente gli esempi - raggiungibile qui: <http://www.urcanet.it/brdp/php_manual/esempi/> - alla sezione riservata al capitolo 8, si trovano due file index.php e menu.php; tramite il primo si accede agli esempi visti fino ad ora, mentre scegliendo il secondo si tratteranno gli script di seguito implementati mediante i quali sarà possibile aggiungere, modificare e rimuovere i contatti dell'utente selezionato. Il codice visto fino ad ora e quello che segue non cura la parte estetica per non appesantire il codice con porzioni di HTML che renderebbero soltanto più faticosa la lettura del listato.

Partendo dal file menu.php, quello che si ottiene è una pagina di selezione simile a quella riportata in figura 300.25.

Figura 300.25. La pagina di selezione permette di scegliere l'operazione da effettuare sui contatti dell'utente associato.

figure/brdp_db_menu

Tramite questa pagina iniziale sarà possibile inserire, modificare e cancellare i contatti degli utenti attivi in archivio. Il codice dello script trattato è il seguente:

1  <?
2    # Includo la classe per la gestione della base di dati
3    include("brdp_db.php");
4
5    $db = new database;
6    $db->connetti();
7
8    $sql = "select * from BRDP_TB_UTENTI where attivo=1";
9  ?>
10
11 <html>
12 <head>
13   <title>Agenda utenti</title>
14 </head>
15 <body>
16
17 <br>
18 [
19  <a href="../../">HOME</a> -
20  <a href="../">ESEMPI</a>
21 ]
22 <br><br>
23 Esempio di <b>interrogazione di base di dati</b>.
24 <br><br>
25 Viene eseguita una SELECT sulla tabella <b>BRDP_TB_UTENTI</b>
26 di tutti gli utenti attivi. <br>Poi viene visualizzato l'elenco con
27 un collegamento generato dinamicamente alla pagina di inserimento, modifica
28 e cancellazione. <br>Dunque da qui verranno richiamate le pagine
29 di gestione dei contatti.
30 <br><br>
31   <i><?=$sql?></i>
32 <br><br>
33 Questo il risultato della query tramite il metodo <b><i>esegui</i></b>:
34 <br><br>
35
36 Gestisci i contatti dell'utente:<br>
37 <ul>
38 <?
39    if($db->esegui($sql) && $db->righe()>0){
40       $i=0;
41       while($i<$db->righe()){    # Questa volta utilizziamo un while
42 ?>
43         <li> <?=$db->leggi($i,"nome")." ".$db->leggi($i,"cognome")?>
44         ----> <a href="inserisci_edita.php?utente=<?=$db->leggi($i,"id_utente")?>">
           <b>Inserisci</b></a>
45         <a href="cancella_scegli.php?utente=<?=$db->leggi($i,"id_utente")?>">
           <b>Cancella</b></a>
46         <a href="modifica_scegli.php?utente=<?=$db->leggi($i,"id_utente")?>">
           <b>Modifica</b></a>
47 <?
48          $i++;
49       }
50    }else{
51       echo "<li>Spiacente, nessun utente attivo!";
52    }
53 ?>
54 </ul>
55 </body>
56 </html>
57
58
59 <?
60   # chiusura della connessione alla base dati è importante!
61   $db->disconnetti();
62 ?>

In linea di principio è molto simile alle precedenti, esegue, infatti, un'interrogazione alla base di dati e cicla tramite una struttura while i valori attenuti. Nel ciclo vengono anche creati i collegamenti alle pagine di gestione passando, in modo dinamico, l'identificativo dell'utente proprietario dei contatti. In particolare ci si riferisce alle righe 44, 45 e 46.

300.7.1   Inserimento di un nuovo contatto

Di seguito si analizzerà l'inserimento di un nuovo contatto, effettuato tramite una maschera di inserimento dati che viene inviata ad una seconda pagina la quale effettua il salvataggio dei dati nella tabella BRDP_TB_AGENDA.

Il file inserisci_edita.php permette di editare i campi di testo che verranno spediti al file inserisci_salva.php, il quale salverà i dati in archivio senza effettuare controlli di alcun genere: dunque anche i campi vuoti saranno inseriti.

In un sito curato e sicuro vengono effettuati controlli Javascript al momento dell'inoltro del modulo, questo aspetto esula dallo scopo della guida ma è bene tenerlo presente al momento della scrittura di un codice efficiente e professionale.

Di seguito il listato della pagina contenente la maschera di inserimento:

1
2  <html>
3  <head>
4    <title>Agenda utenti</title>
5  </head>
6  <body>
7
8  <br>
9  [
10  <a href="../../">HOME</a> -
11  <a href="../">ESEMPI</a> -
12  <a href="menu.php">Inizio ESEMPIO</a>
13 ]
14 <br><br>
15 Esempio di <b>inserimento valori in una base di dati</b>.
16 <br><br>
17 In questa pagina non viene eseguita nessuna connessione alla base di dati.<br>
18 Viene richiesto l'inserimento dei dati da salvare nell'agenda dell'utente scelto
19 nella pagina precedente.
20 <br><br>
21
22 <form action="inserisci_salva.php" method="get">
23
24    <input type="hidden" name="utente" value="<?=$HTTP_GET_VARS["utente"]?>">
25
26    Nome: <input type="text" name="nome" size="30" maxlength="30"><br>
27    Cognome: <input type="text" name="cognome" size="30" maxlength="30"><br>
28    e-mail: <input type="text" name="email" size="30" maxlength="30"><br>
29    Telefono: <input type="text" name="tel" size="20" maxlength="20"><br>
30    Fax: <input type="text" name="fax" size="20" maxlength="20"><br><br>
31
32    <input type="reset" value="ANNULLA">
33    <input type="submit" value="INSERISCI">
34
35 </form>
36
37 </body>
38 </html>
39

Non ci sono particolari complicazioni, il codice è puro HTML che formatta il modulo. Va notato però che alla riga 24 viene passato in modo nascosto il valore dell'identificativo dell'utente proprietario del nuovo contatto, esso viene preso dall'array $HTTP_GET_VARS dei valori ricevuti tramite il metodo get e inviato alla pagina successiva.

Come è facile immaginare il risultato del listato appena visto è il seguente:

Figura 300.28. Da questa pagina è possibile inserire il nuovo contatto per l'utente precedentemente selezionato.

figure/brdp_db_inserisci_edita

Il file inserisci_salva.php riceve i valori e li formatta nella sintassi SQL che effettua una INSERT nella tabella. Ecco il codice nel dettaglio:

1  <?
2    # Includo la classe per la gestione della base di dati
3    include("brdp_db.php");
4
5    $db = new database;
6    $db->connetti();
7
8    settype($HTTP_GET_VARS["utente"],integer);
9
10   $sql = " insert into BRDP_TB_AGENDA
11             (
12                id_utente,
13                Nome,
14                Cognome,
15                email,
16                telefono,
17                fax
18             )values(
19                ".$HTTP_GET_VARS["utente"].",
20                '".$HTTP_GET_VARS["nome"]."',
21                '".$HTTP_GET_VARS["cognome"]."',
22                '".$HTTP_GET_VARS["email"]."',
23                '".$HTTP_GET_VARS["tel"]."',
24                '".$HTTP_GET_VARS["fax"]."'
25             )
26          ";
27 ?>
28
29 <html>
30 <head>
31   <title>Agenda utenti</title>
32 </head>
33 <body>
34
35 <br>
36 [
37  <a href="../../">HOME</a> -
38  <a href="../">ESEMPI</a> -
39  <a href="menu.php">Inizio ESEMPIO</a>
40 ]
41 <br><br>
42 Esempio di <b>interrogazione di base di dati</b>.
43 <br><br>
44 Viene eseguita una INSERT sulla tabella <b>BRDP_TB_AGENDA</b>
45 relazionando il nuovo contatto con l'utente tramite il campo id_utente
46 <br><br>
47   <i><?=$sql?></i>
48 <br><br>
49 Questo il risultato della query tramite il metodo <b><i>esegui</i></b>:
50 <br><br>
51
52 Salvataggio nuovo contatto nell'agenda dell'utente
53 con id_utente: <?=$HTTP_GET_VARS["utente"]?><br>
54 <ul>
55    <?
56       if($HTTP_GET_VARS["utente"]!="" && $HTTP_GET_VARS["utente"]!=0){
57          if($db->esegui($sql)){
58             echo "<li> <b>Inserimento eseguito Correttamente</b>!";
59             # estraggo l'id del nuovo contatto
60             echo "<br> l'ID del nuovo contatto è: ".$db->getlast_id();
61          }else{
62             echo "<li> <b>Inserimento NON eseguito</b>.";
63          }
64       }else{
65          echo "<li> Il percorso seguito non è corretto! Partire da 'menu.php'";
66       }
67    ?>
68 </ul>
69
70 <br>
71 <a href="agenda.php?utente=<?=$HTTP_GET_VARS["utente"]?>">
   Visualizza l'agenda aggiornata</a>.
72
73 </body>
74 </html>
75
76
77 <?
78   # chiusura della connessione alla base dati è importante!
79   $db->disconnetti();
80 ?>

Oltre alle normali operazioni di connessione, viene impostato come intero l'identificativo utente alla riga 8, poi dalla 10 alla 26 viene formattata la query per l'inserimento. Si noti ancora come i valori di tipo stringa vengono contenuti tra singoli apici, mentre i valori interi non hanno bisogno di limitatori; la stringa, inoltre, è generata dinamicamente in base ai valori ricevuti.

Alla riga 56 e 57 vengono effettuati due controlli che permettono di evitare comportamenti ambigui, anche quando il visitatore arriva per errore nella pagina senza aver seguito il percorso corretto, ad esempio in seguito all'apertura della stessa dall'elenco delle preferite. Questo per quanto riguarda il primo controllo; il secondo, invece, verifica la corretta esecuzione della query come più volte trattato.

Più interessante invece è la riga 60 nella quale viene estratto l'identificativo del contatto appena creato tramite il metodo getlast_id della classe database. Tale metodo è utilizzabile in caso di tabelle aventi come chiave primaria un intero autoincrementante ed è il caso della tabella in esempio; l'identificativo del nuovo contatto, infatti, non è stato specificato perchè sarà il DBMS ad assegnarlo in modo progressivo ad ogni nuova voce inserita. Ovviamente il valore è l'ultimo inserito dalla connessione attiva e non l'ultimo in assoluto dal momento che più visitatori in modo concorrente possono inserire valori nella tabella.

La pagina di salvataggio restituisce la seguente risposta:

Figura 300.30. La pagina informa l'utente dell'esito dell'operazione e in caso positivo mostra l'ID assegnato al nuovo contatto.

figure/brdp_db_inserisci_salva

300.7.2   Rimozione di un contatto

Oltre all'inserimento, è possibile eliminare e modificare voci già esistenti; di seguito verrà trattata la procedura di cancellazione. Come prima cosa va identificata univocamente la voce da rimuovere dall'archivio; tramite il menu iniziale cliccando sulla voce "cancella" associata ad uno degli utenti proprietari di una rubrica si passa il parametro utente alla pagina cancella_scegli.php. Tale file mostrerà tutti i contatti associati all'utente mediante il metodo query2select mostrando una scelta di questo tipo:

Figura 300.31. Tramite questa pagina è possibile scegliere il contatto da rimuovere.

figure/brdp_db_cancella_scegli

Il codice, ormai familiare, per ottenere tale risultato è:

1  <?
2    # Includo la classe per la gestione della base di dati
3    include("brdp_db.php");
4
5    $db = new database;
6    $db->connetti();
7
8    $sql = "select * from BRDP_TB_AGENDA where id_utente=".$HTTP_GET_VARS["utente"];
9  ?>
10 
11 <html>
12 <head>
13   <title>Agenda utenti</title>
14 </head>
15 <body>
16 
17 <br>
18 [ 
19 <a href="../../">HOME</a> - 
20 <a href="../">ESEMPI</a> - 
21 <a href="menu.php">Inizio ESEMPIO</a>
22 ]
23 <br><br>
24 Esempio di <b>interrogazione di base di dati</b>.
25 <br><br>
26 Viene eseguita una SELECT sulla tabella <b>BRDP_TB_AGENDA</b>
27 per visualizzare l'elenco dei contatti dell'utente.<br>
28 Il contatto scelto potrà essere rimosso.
29 <br><br>
30   <i><?=$sql?></i>
31 <br><br>
32 Questo il risultato della query tramite il metodo <b><i>query2select</i></b>:
33 <br><br>
34 
35 <form method="get" action="cancella_esegui.php">
36    <input type="hidden" name="utente" value="<?=$HTTP_GET_VARS["utente"]?>">
37    Seleziona il contatto da eliminare <b><?=$HTTP_GET_VARS["nome"]?></b>: &nbsp;
38    <select name="contatto" onchange>
39       <option value="Nessuno" selected>Nessuno</option>
40       <?
41       $db->query2select($sql, "nome", "id_agenda", false, true);
42       ?>
43 </select> &nbsp;
44 <input type="submit" value="Elimina selezionato">
45 </form>
46 
47 </body>
48 </html>
49 
50 
51 <?
52   # chiusura della connessione alla base dati è importante!
53   $db->disconnetti(); 
54 ?>

Il metodo trattato è stato ampliamente spiegato, da notare, ancora, la costruzione dinamica della query nella riga 8, al lettore il compito di implementare i controlli del caso.

Il modulo HTML trasmette il codice utente ottenuto in questa pagina insieme al codice del contatto scelto per essere rimosso. Di seguito il codice della pagina che effettua la rimozione.

1  <?
2    # Includo la classe per la gestione della base di dati
3    include("brdp_db.php");
4
5    $db = new database;
6    $db->connetti();
7
8    settype($HTTP_GET_VARS["utente"],integer);
9
10   $sql = " delete from BRDP_TB_AGENDA where id_agenda = ".$HTTP_GET_VARS["contatto"];
11 ?>
12
13 <html>
14 <head>
15   <title>Agenda utenti</title>
16 </head>
17 <body>
18
19 <br>
20 [
21 <a href="../../">HOME</a> -
22 <a href="../">ESEMPI</a> -
23 <a href="menu.php">Inizio ESEMPIO</a>
24 ]
25 <br><br>
26 Esempio di <b>interrogazione di base di dati</b>.
27 <br><br>
28 Viene eseguita una DELETE sulla tabella <b>BRDP_TB_AGENDA</b>
29 per eliminare gli utenti con id_agenda pari al valore ricevuto
30 dalla select precedente.
31 <br><br>
32   <i><?=$sql?></i>
33 <br><br>
34 Questo il risultato della query tramite il metodo <b><i>esegui</i></b>:
35 <br><br>
36
37 Cancellazione di un contatto dall'agenda dell'utente:<br>
38 <ul>
39    <?
40       if($HTTP_GET_VARS["contatto"]!="" && $HTTP_GET_VARS["contatto"]!=0){
41          if($db->esegui($sql)){
42             echo "<li> <b>Cancellazione eseguita Correttamente</b>!";
43          }else{
44             echo "<li> <b>Cancellazione NON eseguita</b>.";
45          }
46       }else{
47          echo "<li> Nessun contatto specificato.";
48       }
49    ?>
50 </ul>
51
52 <br>
53 <a href="cancella_scegli.php?utente=<?=$HTTP_GET_VARS["utente"]?>">
   Cancella un altro contatto</a>.
54
55
56 </body>
57 </html>
58
59
60 <?
61   # chiusura della connessione alla base dati è importante!
62   $db->disconnetti();
63 ?>

Come al solito la query viene costruita utilizzando i parametri ricevuti dalla pagina precedente. Prima di procedere è bene far notare che un parametro ricevuto non viene utilizzato; questa non è una distrazione di chi scrive, è semplicemente compito del lettore inserirlo in modo corretto nella query. Ovviamente il funzionamento è garantito anche in questa versione del codice grazie all'univocità della chiave di identificazione del contatto.

Alla riga 40 viene controllato che sia stato specificato il codice della voce da rimuovere, senza controllare che si tratti di un intero. Si provi a modificare la barra dell'indirizzo assegnando una stringa al parametro rappresentante il codice del contatto per verificare la gestione dell'errore. Con l'aggiunta di un controllo si può gestire più in dettaglio l'anomalia, l'esercizio è lasciato al lettore.

Alla riga 41 viene controllata l'esecuzione dell'istruzione, il risultato di questo programma è il seguente:

Figura 300.34. Il risultato dell'operazione di rimozione.

figure/brdp_db_cancella_esegui

300.7.3   Modifica di un contatto

Per rendere funzionante il prototipo di questa rudimentale rubrica non manca che implementare la parte di modifica dei contatti presenti in archivio. Partendo dal file principale menu.php, scegliendo la voce "modifica" si accede alla pagina modifica_scegli.php che permette di scegliere il contatto da editare; questa pagina è un clone di cancella_scegli.php, con l'unica differenza sulla pagina di destinazione a cui punta, dunque risulta inutile riproporne il codice. Ecco come si presenta:

Figura 300.35. Del tutto simile a cancella_scegli.php; a cambiare è la pagina di destinazione modifica_modifica.php.

figure/brdp_db_modifica_scegli

La modifica avverrà tramite una maschera simile a quella di inserimento, con la differenza che i campi saranno valorizzati con i dati presenti nella base di dati, in modo che il visitatore possa modificare uno o più campi e salvare i nuovi valori. Il codice per ottenere tale risultato è il seguente:

1  <?
2    # Includo la classe per la gestione della base di dati
3    include("brdp_db.php");
4
5    $db = new database;
6    $db->connetti();
7
8    $sql = "select * from BRDP_TB_AGENDA where id_agenda=".$HTTP_GET_VARS["contatto"];
9  ?>
10
11 <html>
12 <head>
13   <title>Agenda utenti</title>
14 </head>
15 <body>
16
17 <br>
18 [
19 <a href="../../">HOME</a> -
20 <a href="../">ESEMPI</a> -
21 <a href="menu.php">Inizio ESEMPIO</a>
22 ]
23 <br><br>
24 Esempio di <b>interrogazione di base di dati</b>.
25 <br><br>
26 Viene eseguita una SELECT sulla tabella <b>BRDP_TB_AGENDA</b>
27 per visualizzare i campi relativi al contatto da modificare.
28 <br><br>
29   <i><?=$sql?></i>
30 <br><br>
31 Ecco i valori ottenuti tramite il metodo <b><i>esegui</i></b>
32 <br><br>
33
34 <? if($db->esegui($sql) && $db->righe()==1){ ?>
35    <form method="get" action="modifica_salva.php">
36       <input type="hidden" name="utente" value="<?=$HTTP_GET_VARS["utente"]?>">
37       <input type="hidden" name="contatto" value="<?=$HTTP_GET_VARS["contatto"]?>">
38
39       Nome: <input type="text" name="nome" value="<?=$db->leggi(0,"nome")?>" size="30"
         maxlength="30"><br>
40       Cognome: <input type="text" name="cognome" value="<?=$db->leggi(0,"cognome")?>"
         size="30" maxlength="30"><br>
41       e-mail: <input type="text" name="email" value="<?=$db->leggi(0,"email")?>"
         size="30" maxlength="30"><br>
42       Telefono: <input type="text" name="tel" value="<?=$db->leggi(0,"telefono")?>"
         size="20" maxlength="20"><br>
43       Fax: <input type="text" name="fax" value="<?=$db->leggi(0,"fax")?>" size="20"
         maxlength="20"><br><br>
44
45       <input type="reset" value="Annulla le modifiche">
46       &nbsp;&nbsp;&nbsp;
47       <input type="submit" value="Salva le modifiche">
48    </form>
49 <? }else{ ?>
50       <b>Nessun utente da modificare.</b>
51 <? } ?>
52
53 <br>
54 <a href="modifica_scegli.php?utente=<?=$HTTP_GET_VARS["utente"]?>">Scegline un altro</a>.
55
56 </body>
57 </html>
58
59
60 <?
61   # chiusura della connessione alla base dati è importante!
62   $db->disconnetti();
63 ?>

L'interazione del PHP con l'HTML in questo esempio è più evidente. Una volta selezionati i dati dall'archivio vengono mostrati nei campi del modulo tramite le righe dalla 39 alla 43, mentre alle righe 36 e 37 vengono valorizzati i campi nascosti contenenti il valore del codice utente e del codice contatto.

Il controllo alla riga 34 è ormai chiaro, esso verifica che la query venga eseguita correttamente e che restituisca una sola riga. Se le due condizioni non si verificano contemporaneamente viene visualizzato un messaggio di errore. Questo è il risultato del codice appena visto:

Figura 300.37. Tramite il modulo è possibile modificare uno o più campi salvando i nuovi valori nella base di dati.

figure/brdp_db_modifica_edita

A questo punto il visitatore può modificare i campi che preferisce ed inviare il tutto alla pagina successiva che provvederà al salvataggio nella base di dati dei nuovi valori. Lo script che si occupa di questa ultima operazione è modifica_salva.php di cui viene riportato il codice di seguito:

1  <?
2   # Includo la classe per la gestione della base di dati
3   include("brdp_db.php");
4
5   $db = new database;
6   $db->connetti();
7
8   settype($HTTP_GET_VARS["contatto"],integer);
9
10   $sql = " update
11                BRDP_TB_AGENDA
12             set
13                Nome = '".$HTTP_GET_VARS["nome"]."' ,
14                Cognome = '".$HTTP_GET_VARS["cognome"]."' ,
15                email = '".$HTTP_GET_VARS["email"]."' ,
16                telefono = '".$HTTP_GET_VARS["tel"]."' ,
17                fax = '".$HTTP_GET_VARS["fax"]."'
18             where
19                id_agenda = ".$HTTP_GET_VARS["contatto"]."modifica
20          ";
21 ?>
22
23 <html>
24 <head>
25   <title>Agenda utenti</title>
26 </head>
27 <body>
28 
29 <br>
30 [ 
31 <a href="../../">HOME</a> - 
32 <a href="../">ESEMPI</a> -
33 <a href="menu.php">Inizio ESEMPIO</a> 
34 ]
35 <br><br>
36 Esempio di <b>interrogazione di base di dati</b>.
37 <br><br>
38 Viene eseguita una UPDATE sulla tabella <b>BRDP_TB_AGENDA</b>
39 del solo utente con id_contatto pari a quello ricevuto in get
40 <br><br>
41   <i><?=$sql?></i>
42 <br><br>
43 Questo il risultato della query tramite il metodo <b><i>esegui</i></b>:
44 <br><br>
45 
46 Salvataggio modifiche:<br>
47 <ul>
48    <?
49       if($HTTP_GET_VARS["contatto"]!="" && $HTTP_GET_VARS["contatto"]!=0){
50          if($db->esegui($sql)){
51             echo "<li> <b>Modifiche salvate Correttamente</b>!";
52          }else{
53             echo "<li> <b>Salavtaggio modifiche NON eseguito</b>.";
54          }
55       }else{
56          echo "<li> Il percorso seguito non è corretto! Partire da 'menu.php'";
57       }
58    ?>
59 </ul>
60 
61 <br>
62 <a href="agenda.php?utente=<?=$HTTP_GET_VARS["utente"]?>">Visualizza
   l'agenda aggiornata</a>.
63 
64 </body>
65 </html>
66 
67 
68 <?
69   # chiusura della connessione alla base dati è importante!
70   $db->disconnetti();
71 ?>

Dalla riga 10 alla 20 viene costruita la query, la quale non è complessa ma richiede attenzione particolare come nel caso della cancellazione; infatti, se non viene specificata la condizione di WHERE corretta si rischia di apportare la stessa modifica a più righe. Nel caso peggiore si potrebbero modificare le righe della tabella rendendole tutte uguali se si omettesse la clausola di riga 18 e 19.

Il risultato è simile ai precedenti e viene riportato di seguito:

Figura 300.39. Viene visualizzata la query e mostrato l'esito della sua esecuzione.

figure/brdp_db_modifica_salva

300.8   Conclusioni

Con la gestione delle modifiche si può considerare completa l'applicazione di esempio; essa ovviamente va presa come un ripetitivo utilizzo dei metodi della classe database ed ha come scopo unico quello di acquisire dimestichezza con la gestione delle base di dati tramite il PHP.

Come prima cosa non è stato minimamente tenuto conto dell'aspetto grafico e della impaginazione dei dati: non è una mancanza ma una scelta. In questo modo il codice è velocemente leggibile e si è evitato di perdere di vista l'obiettivo degli esempi. Ognuno poi nelle proprie applicazioni potrà integrare il codice nella veste grafica del proprio sito come meglio crede.

Per lo stesso motivo non sono stati implementati controlli Javascript per non divagare in argomenti non strettamente inerenti questa guida. Inutile dire che non si può fare a meno di tali controlli in un sito di qualità, l'invito quindi è a documentarsi anche su questo linguaggio se si vuole implementare un prodotto di qualità.

Tutti i controlli sui dati ricevuti dalle pagine di inserimento, cancellazione e modifica sono stati trascurati per lo stesso motivo sopra citato. Un esempio per tutti: un indirizzo email non può non contenere il carattere '@', come deve contenere per forza almeno un carattere '.' oltre alla lunghezza che non può essere inferiore a sette caratteri (a@bc.de ovviamente è un limite plausibile). Prima di inserire dati in un archivio è bene tenere conto di queste problematiche; si pensi, ad esempio, ad una anagrafica utenti di un negozio virtuale in cui la metà degli indirizzi email dei clienti registrati è falso o vuoto: non sarà possibile contattare in alcun modo gli utenti iscritti per campagne pubblicitarie sui nuovi prodotti.

Infine prima di iniziare a lavorare sulla base di dati tramite codice è bene assicurarsi di avere i permessi necessari per effettuare le operazioni eseguite nel codice. Se ad esempio l'utente con cui ci si collega (impostato nella classe) non ha i permessi di cancellazione, allora una query che effettua una DELETE non verrà mai eseguita, non a causa di problemi nel codice ma per mancanza di permessi nella configurazione del DBMS. Dunque, come prima cosa è bene testare il funzionamento dei vari comandi SQL da linea di comando prima di passare all'esecuzione degli stessi dal PHP.

Programmare in PHP --- Copyright © 2001-2003, 2005 Gianluca Giusti -- <brdp (ad) urcanet·it>


1) L'elenco delle base di dati gestite dal PHP è riportato nella sezione 293.2.

2) Acronimo di DataBase Management System ovvero il sistema di gestione delle base di dati.

3) Acronimo di Structured Query Lenguage.

4) È il caso di applicazioni Web generiche che devono essere personalizzabili secondo le necessità dettate da strutture già esistenti. Ad esempio un gestore di banner pubblicitari deve appoggiarsi su strutture già esistenti come quelle di un portale e spesso viene integrato nella base di dati a disposizione. In questo caso il prodotto deve gestire i diversi DBMS altrimenti resterebbe tagliato fuori da una o più fette di mercato.


Dovrebbe essere possibile fare riferimento a questa pagina anche con il nome il_php_e_le_base_di_dati.htm

[successivo] [precedente] [inizio] [fine] [indice generale] [indice ridotto] [translators] [docinfo] [indice analitico]

Valid ISO-HTML!

CSS validator!