Database MySQL e PHP

Venerdì, 17 Dicembre 2004

OBIETTIVI DELLA LEZIONE

In questa lezione:

  1. Impareremo ad interrogare un database SQL da PHP
  2. Upload di file e date in PHP
  3. Sessioni un po' più sicure

MySQL

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) lez15e16
(2) Sul server una CGI riceve i dati Server + Programma PHP lez17e18
(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 lez17e18

In questa sezione ci concentriamo sul punto (3). Il processo è schematizzato in questa figura.





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:

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

PhpMyAdmin è un pacchetto di script PHP che ci permetterà di interagire molto più semplicemente con il server MySQL [Benissimo!].

Ad esempio, vediamo in queste immagini la creazione del database "db_annunci" e della tabella "annunci", come fatto in SQL nella sezione precedente.

  1. Viene inserito il nome del database da creare da creare. [Immagine]
  2. Viene inserito il nome della tabella da creare e il numero di campi che la tabella deve avere. [Immagine]
  3. Vengono specificati i nomi dei campi e il tipo di ciascun campo. [Immagine]
  4. La tabella è stata creata ed è possibile inserire nuovi record. [Immagine]

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.

PHP + MySQL

L'accesso al database MySQL da PHP si compone SEMPRE dei seguenti passi:

  1. apertura della connessione al database MySQL;
  2. selezione del database su cui operare;
  3. esecuzione query SQL sul database;
  4. lettura dei risultati della query;
  5. eliminazione dei risultati della query (NON NECESSARIO);
  6. chiusura della connessione.

Esempio 1

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>

Esempio 2

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>

Esempio 3

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 db_annunci e la tabella annunci ha la struttura vista sopra.

Upload di immagini

Quando si fa l'upload di una immagine sul server (cioè il client invia al server una intera immagine che quest'ultimo salva sul suo file system) il modulo PHP la rende disponibile al nostro script nella variabile super globale $_FILES. Esattamente come troveremmo nell'array $_POST le variabili inviate con il metodo post.

Se il nostro controllo si chiama "miofile", $_FILES["miofile"] contiene:

Da notare:

Ecco un esempio: upload1.php (funziona solo all'interno del polo di Crema)

<html>
<head>
<title>Upload di una immagine</title>
</head>
<body>
<?php
    $remote_ip_chunk = explode(".", $_SERVER['REMOTE_ADDR']);
    $server_ip_chunk = explode(".", $_SERVER['SERVER_ADDR']);
    $remote_ip=$remote_ip_chunk[0] . $remote_ip_chunk[1];
    $server_ip=$server_ip_chunk[0] . $server_ip_chunk[1];
    if( $remote_ip !== $server_ip )
    {
        print "Questo script funziona solo all'interno del Polo di Crema!\n";
        print "</body>\n</html>\n";
        exit;
    }

?>
<?php
if( !isset($_FILES['immagine']) )
{
?>
<h3>Seleziona l'immagine da caricare sul server:</h3>
<form action="<?php print $_SERVER['PHP_SELF']; ?>" method="post"
    enctype="multipart/form-data">

<input type="hidden" name="MAX_FILE_SIZE" value="30000" />
<input type="file" name="immagine">
<input type="submit" value="Invia l'immagine">
</form>
<?php
}
else
{
    if($_FILES['immagine']['error']!==UPLOAD_ERR_OK)
    {
        print "<h3>L'immagine non è stata caricata. Riprova.</h3>\n";
    }
    else
    {
        # il file va spostato da qualche parte perchè ora è in
        # una cartella temporanea
        $file_destinazione="./img/" . $_FILES['immagine']['name'];
        if( move_uploaded_file($_FILES['immagine']['tmp_name'], $file_destinazione) )
        {
            print "<h3>L'immagine è stata caricata. Eccola:</h3>\n";
            print "<img src=\"$file_destinazione\" />\n";
            print "<br /><br />\n";
            print "Dimensioni di <b>{$_FILES['immagine']['name']}</b>: " .
                "{$_FILES['immagine']['size']} bytes.\n";
        }
        else
        {
            print "<h3>L'immagine non è stata caricata. Riprova.</h3>\n";
        }
    }
}

?>
</body>
</html>

Funzioni Utili

Sessioni un po' più sicure

Durante la scorsa lezione abbiamo imparato cosa è una sessione HTTP e come si gestisce in PHP. Dal punto di vista del programmatore è molto semplice, basta aggiungere la funzione session_start() all'inizio di ciascuno dei files che dovranno fare parte della sessione. Il programma PHP disporrà delle variabili di sessione (persistenti per la durata della sessione) nella variabile superglobale $_SESSION.

Critico per la sicurezza di una sessione è il fatto che l'ID di sessione viaggia in un cookie e può essere carpito durante il viaggio tra server al client. Vediamo 3 regole per rendere una sessione decentemente sicura:

  1. Usare sempre un cookie per il trasporto dell'ID di sessione. [Non abbiamo visto alcun altro metodo, ma ne esistono altri più problematici. Ad esempio l'ID può essere trasportato tramite un hidden input con il metodo GET. Meglio evitarli.]
  2. Stabilire sempre, quando possibile, connessioni su socket SSL. Come fare? E' semplicissimo, vediamolo in un esempio:
    function verifica_SSL()
    {
        if( $_SERVER['HTTPS'] !== 'on' )
        {
            # La connessione non è su socket SSL; invita il browser del client a
            # ricaricare la stessa pagina tramite HTTPS
            header("Location: https://{$_SERVER['SERVER_NAME']}{$_SERVER['PHP_SELF']}");
            exit;
        }
    
        # Imposta opzione "cookie_secure": il cookie di sessione verrà
        # restituito dal client solo su SSL
        ini_set("session.cookie_secure", TRUE);
    }
  3. Quando possibile, memorizzare in una variabile di sessione l'IP del client e NON accettare connessioni successive se non dallo stesso IP. L'indirizzo IP del client è contenuto nella variabile superglobale
    $_SERVER['REMOTE_ADDR']).

Lab

Esercizio 1: Prendiamo confidenza con MySQL e PhpMyAdmin

Create un database che abbia come nome il vostro account (esempio: rsassi). Create all'interno del database 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.

©2004 Roberto Sassi