OBIETTIVI DELLA LEZIONE
In questa lezione:
- Impareremo ad interrogare un database SQL da PHP
- Vedremo cosa sono le sessioni e perchè servono
- Miglioreremo la conoscenza di base del linguaggio PHP
Contestualizzazione:
Il processo di creazione dinamica di una pagina HTML può essere schematizzato nei seguenti passi fondamentali:
(1) | Invio dei dati dal client al server | form HTML + richiesta HTTP (GET/POST) | lez13e14 |
(2) | Sul server una CGI riceve i dati | Server + Programma PHP | lez15e16 |
(3) | La CGI interroga il DB MySQL | query MySQL | Oggi |
(4) | Con i risultati ottenuti crea la pagina da rimandare all'utente | Programma PHP + Server | lez15e16 |
In questa sezione ci concentriamo sul punto (3).
MySQL è un server di database relazionale,
in parte conforme allo standard SQL92. In termini
molto rozzi, un database relazionale è un insieme di tabelle
e di relazioni tra alcuni campi di tabelle diverse.
Per quanto riguarda il nostro corso chiameremo con il
nome di "record" ciascuna riga di una tabella e
con quello di "campo" ciascuna colonna.
MySQL può essere interrogato attraverso un dialetto
del linguaggio standard SQL.
Vediamo attraverso alcuni esempi una possibile sessione:
CREATE DATABASE db_annunci;
\u db_annunci
CREATE TABLE annunci ( id INT UNSIGNED NOT NULL AUTO_INCREMENT, data DATE NOT NULL, testo TEXT NOT NULL, matricola VARCHAR( 6 ) NOT NULL, PRIMARY KEY ( id ) );
INSERT INTO annunci (data, testo, matricola) VALUES ('2004-05-02', 'Vendo VESPA 125 da sistemare. Luigi 333123456', '123456');
DELETE FROM annunci WHERE id=5;
UPDATE annunci SET testo='Vendo VESPA 200 da sistemare. Luigi 333 1234567', matricola='123457' WHERE id=5;
SELECT * FROM annunci;
SELECT * FROM annunci WHERE testo LIKE '%vendo%' AND testo LIKE '%vespa%';
DROP TABLE annunci;
DROP DATABASE db_annunci;
I comandi SQL (SELECT ad esempio) e i nomi delle colonne (i campi) non sono case-sensitive. Sono invece case-sensitive in MySQL i nomi dei database e delle tabelle.
ATTENZIONE: i comandi SQL riportati sopra terminano con il punto e virgola (;). Quando li effettuaremo da PHP, anche se per il resto la sintassi sarà IDENTICA, il punto e virgola finale NON DEVE ESSERE INSERITO.
PhpMyAdmin è un pacchetto di script PHP che ci permetterà di interagire molto più semplicemente con il server MySQL [Benissimo!].
Ad esempio la vediamo in queste immagini la creazione del database "db_annunci" e della tabella "annunci", come fatto in SQL nella sezione precedente.
Anche se PhpMyAdmin permette di fare molto di più di quanto visto, in generale servirà più che altro per creare la struttura del database. I dati verranno inseriti dagli script PHP.
L'accesso al database MySQL da PHP si compone SEMPRE dei seguenti passi:
$ptr_mysqls=mysql_connect("localhost","rsassi","rsassi") or die("Impossibile connettersi al server MySQL.\n");
mysql_select_db("db_annunci", $ptr_mysqls) or die("Impossibile aprire il database.\n");
$query="SELECT * FROM annunci"; $ptr_risultato_query=mysql_query($query, $ptr_mysqls);
$numero_records=mysql_affected_rows($puntatore_connessione_aperta);
$numero_campi=mysql_num_fields($ptr_risultato_query);
// $i è un numero da 1 a $numero_campi $nome_campo=mysql_field_name($ptr_risultato_query, $i-1);Attenzione: i campi sono numerati a partire da 0!
$record=mysql_fetch_array($ptr_risultato_query, MYSQL_ASSOC);$record è un array associativo che contiene tanti elementi quanti sono i campi contenuti nella risposta ($numero_campi). Le chiave di ciascun elemento è il nome del campo corrispondente.
// $i è un numero da 1 a $numero_records mysql_data_seek($ptr_risultato_query, $i-1) or die("Impossibile posizionarsi sul record $i\n"); $record=mysql_fetch_array($ptr_risultato_query, MYSQL_ASSOC);Attenzione: i record sono numerati a partire da 0!
mysql_free_result($ptr_risultato_query);
mysql_close($ptr_mysqls);
esempiosql1.php conta i records contenuti nella tabella annunci del database db_annunci, visto sopra.
<html>
<head>
<title>Bacheca annunci</title>
</head>
<body>
<?php
$ptr_mysqls=mysql_connect("localhost","root","")
or die("Impossibile connettersi al server MySQL.\n");
mysql_select_db("db_annunci", $ptr_mysqls)
or die("Impossibile aprire il database.\n");
$query_visualizzazione="SELECT * FROM annunci";
$ptr_risultato_query=mysql_query($query_visualizzazione, $ptr_mysqls);
$numero_records=mysql_affected_rows($ptr_mysqls);
print "Il database contiene $numero_records annunci.\n";
mysql_free_result($ptr_risultato_query);
mysql_close($ptr_mysqls);
?>
</body>
</html>
esempiosql2.php visualizza tutti i records della tabella annunci
<html>
<head>
<title>Bacheca annunci</title>
</head>
<body>
<?php
$ptr_mysqls=mysql_connect("localhost","root","")
or die("Impossibile connettersi al server MySQL.\n");
mysql_select_db("db_annunci", $ptr_mysqls)
or die("Impossibile aprire il database.\n");
$query_visualizzazione="SELECT * FROM annunci";
$ptr_risultato_query=mysql_query($query_visualizzazione, $ptr_mysqls);
print "<table cellpadding=\"3\" border=\"1\">\n";
while( $record=mysql_fetch_array($ptr_risultato_query, MYSQL_ASSOC) )
{
print "<tr>\n";
foreach($record as $valore_campo)
{
print "<td>\n";
print $valore_campo . "\n";
print "</td>\n";
}
print "</tr>\n";
}
print "</table>\n";
mysql_free_result($ptr_risultato_query);
mysql_close($ptr_mysqls);
?>
</body>
</html>
Sito dove gli studenti possono inserire le loro inserzioni. L'esempio è più complesso e costituito da tre files. annunci0.php è la pagina principale, inserisci0.php permette di inserire un nuovo annuncio e cancella0.php cancella un annuncio dal database. Il database è sempre bd_annunci e la tabella annunci ha la struttura vista sopra.
<html>
<head>
<title>Bacheca annunci</title>
</head>
<body>
<h2>Bacheca Annunci</h2>
<h3>(riservata agli studenti del polo di Crema)</h3><br />
<?php
$ptr_mysqls=mysql_connect("localhost","root","")
or die("Impossibile connettersi al server MySQL.\n");
mysql_select_db("db_annunci", $ptr_mysqls)
or die("Impossibile aprire il database.\n");
$query_visualizzazione="SELECT * FROM annunci";
if( isset($_GET["parola"]) and ($_GET["parola"]!=="") )
$query_visualizzazione .= " WHERE testo LIKE '%{$_GET['parola']}%'";
$ptr_risultato_query=mysql_query($query_visualizzazione, $ptr_mysqls);
$numero_records=mysql_affected_rows($ptr_mysqls);
if($numero_records !== 0)
{
print "<table cellpadding=\"3\" border=\"1\" width=\"550\">\n";
print "<tr>\n";
$numero_campi=mysql_num_fields($ptr_risultato_query);
for($i_campo=0; $i_campo<$numero_campi; $i_campo++)
{
print "<th>\n";
print mysql_field_name($ptr_risultato_query, $i_campo) . "\n";
print "</th>\n";
}
print "</tr>\n";
while( $record=mysql_fetch_array($ptr_risultato_query, MYSQL_ASSOC) )
{
print "<tr>\n";
foreach($record as $nome_campo => $valore_campo)
{
if($nome_campo == "testo")
print "<td>\n";
else
print "<td nowrap>\n";
print $valore_campo . "\n";
print "</td>\n";
}
print "</tr>\n";
}
print "</table>\n";
}
else
{
print "<font color=\"#FF0000\">";
print "Il database è vuoto o nessuna inserzione contiene la parola inserita.";
print "</font><br />\n";
}
mysql_free_result($ptr_risultato_query);
mysql_close($ptr_mysqls);
?>
<br/><br/>
<a href="inserisci0.php">Inserisci un nuovo annuncio</a>
<br />
<form action="cancella0.php" method="get">
Cancella l'annuncio numero:
<input type="text" name="id_annuncio" size="3">
<input type="submit" value="Cancella">
</form>
<form action="<?php print $_SERVER["PHP_SELF"]; ?>" method="get">
Annunci che contengono questa parola:
<input type="text" name="parola" size="20">
<input type="submit" value="Cerca">
</form>
</body>
</html>
<?php
if( !isset($_POST['testo']) or !isset($_POST['matricola']) )
{
?>
<html>
<head>
<title>Bacheca annunci</title>
</head>
<body>
<h2>Bacheca Annunci<h2>
<h3>(riservata agli studenti del polo di Crema)</h3><br />
<h2>Inserisci un annuncio</h2><br />
<form action="<?php print $_SERVER['PHP_SELF']; ?>" method="POST">
<textarea cols=40 rows=7 name="testo">
</textarea>
<table>
<tr>
<td>Matricola:</td>
<td><input type="text" name="matricola" size="6"></td>
</tr>
</table>
<input type="submit" value="Inserisci!">
</form>
</body>
</html>
<?php
}
else
{
$data=date("Y-m-d");
$ptr_mysqls=mysql_connect("localhost","root","")
or die("Impossibile connettersi al server MySQL.\n");
mysql_select_db("db_annunci", $ptr_mysqls)
or die("Impossibile aprire il database.\n");
$query_inserimento="INSERT INTO annunci (data, testo, matricola) ".
"VALUES('$data', '{$_POST['testo']}', '{$_POST['matricola']}')";
$ptr_risultato_query=mysql_query($query_inserimento, $ptr_mysqls);
if($ptr_risultato_query == FALSE)
{
print "<html>\n";
print "<head>\n";
print "<title>Bacheca annunci</title>\n";
print "</head>\n";
print "<body>\n";
print "<h2>Impossibile inserire l'annuncio.</h2>\n";
print "</body>\n";
print "</html>\n";
}
else
{
header("Location: http://" . $_SERVER['HTTP_HOST'] .
dirname($_SERVER['PHP_SELF']) . "/annunci0.php");
}
mysql_close($ptr_mysqls);
}
?>
<?php
if( !isset($_GET['id_annuncio']) )
{
header("Location: {$_SERVER['HTTP_REFERER']}");
}
else
{
$ptr_mysqls=mysql_connect("localhost","root","")
or die("Impossibile connettersi al server MySQL.\n");
mysql_select_db("db_annunci", $ptr_mysqls)
or die("Impossibile aprire il database.\n");
$query_eliminazione="DELETE FROM annunci WHERE id={$_GET['id_annuncio']}";
$risultato_query=mysql_query($query_eliminazione, $ptr_mysqls);
$numero_record_eliminati=mysql_affected_rows($ptr_mysqls);
if( ($risultato_query == FALSE) or ($numero_record_eliminati==0) )
{
print "<html>\n";
print "<head>\n";
print "<title>Bacheca annunci</title>\n";
print "</head>\n";
print "<body>\n";
print "<h2>Impossibile cancellare l'annuncio.</h2>\n";
print "</body>\n";
print "</html>\n";
}
else
{
header("Location: {$_SERVER['HTTP_REFERER']}");
}
mysql_close($ptr_mysqls);
}
?>
HTTP è un protocollo senza memoria di stato e, di sua natura, ogni coppia
"domanda del client"/"risposta del server"
è indipendente dalle altre.
Una SESSIONE è semplicemente una serie di domande/risposte
effettuate da un client ad un server che condividono uno stato
(condividono informazioni che persistono tra una connessione e
le successive).
Nella lezione 15, abbiamo visto come
sia possibile utilizzare un cookie per far si che il valore
di alcune variabili permanga tra connessioni
indipendenti. Di fatto l'esempio 4
costituiva un primo rudimentale esempio di sessione.
D'altra parte, per applicazioni in cui la sicurezza è critica
il cookie ha un punto debole: le informazioni
che si vogliono conservare tra una pagina e l'altra vengono salvate
in un file sul disco del client e sono quindi modificabili
dall'utente.
Una soluzione a questo problema è quello di mettere nel cookie
un codice identificativo della sessione e salvare le informazioni
che devono essere persistenti sul server.
Un esempio (essessione1.php):
<?php
session_start();
if( !isset($_SESSION['numero_visite']) )
{
$_SESSION['numero_visite']=1;
}
else
{
$_SESSION['numero_visite']++;
}
?>
<html>
<head>
<title>Titolo</title>
</head>
<body>
Il numero di volte che ti sei connesso a questa pagina è
<b><?php print $_SESSION['numero_visite']; ?></b>.
</body>
</html>
HTTP/1.x 200 OK Date: Mon, 10 May 2004 08:07:29 GMT Server: Apache/1.3.26 (Unix) Debian GNU/Linux PHP/4.1.2 mod_ssl/2.8.9 OpenSSL/0.9.6g mod_perl/1.26 X-Powered-By: PHP/4.1.2 Set-Cookie: PHPSESSID=42b93d2d874a2f169896583a9e4d85db; path=/ [...]Inoltre crea sul server un file dove verranno salvate le variabili da conservare per tutta la durata della sessione. Il nome del file contiene il valore di PHPSESSID. As esempio, viene creato il file sess_42b93d2d874a2f169896583a9e4d85db.
GET /~sassi/LIA2003/essessione1.php HTTP/1.1 Host: www.dti.unimi.it [...] Cookie: PHPSESSID=42b93d2d874a2f169896583a9e4d85db [...]mentre il contenuto del file di sessione sess_42b93d2d874a2f169896583a9e4d85db è
numero_visite|i:5;La variabile $_SESSION['numero_visite'] conterrà il valore 5.
// elimina tutte le variabili dalla sessione session_unset(); // chiude la sessione session_destroy();
In questa breve sezione aumentiamo la conoscenza di base del PHP
function nome_della_funzione($parametro1, $parametro2) { // corpo della funzione return $valore_restituito; }Anche per le funzioni, non è necessario specificare né il tipo dei parametri, né il tipo del valore che viene restituito.
<?php
function fattoriale($n)
{
$risultato=1;
for($i=2; $i<=$n; $i++)
$risultato*=$i;
return $risultato;
}
?>
<html>
<head>
<title>Fattoriale di un numero</title>
</head>
<body>
<?php
if( isset($_GET['numero']) )
{
print "Il fattoriale di {$_GET['numero']} è " . fattoriale($_GET['numero']);
}
else
{
?>
<form action="<?php print $_SERVER['PHP_SELF']?>", method="get">
Calcola il fattoriale di
<input type="text" name="numero">
<input type="submit" value="Calcola!">
</form>
<?php
}
?>
</body>
</html>
I parametri sono passati per valore. Se si desidera che un parametro sia
passato per riferimento, nella dichiarazione della funzione bisogna
anteporre l'operatore & al nome della variabile.
<?php
function fattoriale($n, &$risultato)
{
$risultato=1;
for($i=2; $i<=$n; $i++)
$risultato*=$i;
return $risultato;
}
?>
[...]
<?php
if( isset($_GET['numero']) )
{
fattoriale($_GET['numero'], $r);
print "Il fattoriale di {$_GET['numero']} è $r";
}
else
{
[...]
Le funzioni in PHP possono essere ricorsive.
<html> <head> <title>Il mio sito</title> </head> <body> <font color="#FF0000"><h2>IL MIO SITO</h2></font> <hr size="1">ed file footer.inc:
<hr size="1"> Contatta il <a href="mailto:webmaster@ilmiosito.it">WebMaster</a>! </body> </html>ecco lo script che li include (hf.php):
<?php
include("header.inc");
?>
<br />
<h2>Contenuto del sito</h2>
<br />
<?php
include("footer.inc");
?>
CONSIGLIO: usate il manuale PHP!
Il manuale MySQL si scarica dalla pagina
http://dev.mysql.com/doc/ (non è essenziale).
Per prima cosa svolgere gli esercizi della lezione 16
Esercizio 1: Prendiamo confidenza con MySQL e PhpMyAdmin
Una descrizione dettagliata della procedura di connessione al server MySQL attraverso PhpMyAdmin è disponibile all'indirizzo: http://php.weblab.crema.unimi.it . In breve, andate alla pagina http://php.weblab.crema.unimi.it/mysql/ e inserite SIA come username che come password lo username che vi è stato assegnato (solitamente lettera iniziale nome + cognome).
php.weblab pone la restrizione agli utenti di avere un solo database di nome "phpweb[numero del gruppo a cui appartenete]". Quindi non è possibile creare un database, solo aggiungervi delle tabelle (poco importa per il corso e al fine dello svolgimento dell'elaborato).
Create la tabella "annunci" in modo che abbia la struttura degli esempi visti a lezione. Inoltre, tramite PhpMyAdmin aggiungete qualche inserzione (suggerimento: selezionate la tabella e andate alla scheda "Inserisci").
Modificate i file degli esempi 1 e 2 in modo che funzionino dal vostro account: (1) cambiate username e password nella funzione mysql_connect() in modo che coincidano con i vostri dati; (2) cambiate il nome del database nella funzione mysql_select_db(), che nel vostro caso si chiama "phpweb[numero del gruppo a cui appartenete]".
Copiate i files sul webserver. Funzionano?
Esercizio 2
Tramite PhpMyAdmin, create una tabella "spese" che contenga 3 campi: (1) data: la data della spesa; (2) motivo: che cosa avete comperato; (3) importo: quanto avete speso.
Create lo script inseriscispesa.php che permetta all'utente di inserire, tramite un form una spesa effettuata nel database.
Preparare lo script vedispese.php che produca una tabella di tutte le spese effettuate.
Esercizio 3
Preparare lo script memorizzanome1.php che inizia una sessione e, dopo aver chiesto all'utente il nome, lo memorizza nella variabile di sessione "nome". Se "nome" è già contenuto in $_SESSION, presenta all'utente una pagina di saluto contenente il nome dell'utente.
Preparare lo script memorizzanome2.php che legge il valore della variabile di sessione "nome" e presenta all'utente una pagina di benvenuto contenente il nome.
Funzionano entrambi? Chiudete il brower. Apritelo di nuovo e visualizzate memorizzanome2.php. La sessione è ancora aperta?
©2004 Roberto Sassi e Fabio Scotti