PHP: Object oriented - Errori ed eccezioni in PHP - eccezioni, interazione con i DB, sessioni
←
→
Trascrizione del contenuto della pagina
Se il tuo browser non visualizza correttamente la pagina, ti preghiamo di leggere il contenuto della pagina quaggiù
aa 2019/2020
Object‐oriented
PHP:
eccezioni, interazione
con i DB, sessioni
Goy ‐ a.a. 2019/2020 Tecnologie Web: approcci avanzati 1
1
Errori ed
eccezioni in PHP
Goy ‐ a.a. 2019/2020 Tecnologie Web: approcci avanzati 2
2
1aa 2019/2020
PHP: errori ed eccezioni ‐ I
In caso di problemi, PHP genera diversi tipi di errori:
• parser error, errori di sintassi (per es. parentesi mancanti)
• fatal error, che interrompono l'esecuzione del programma (x
es. invocare una funzione non definita)
• warning, possibili anomalie che però non bloccano
l'esecuzione del programma (x es. una divisione per 0)
• notice, segnalazioni non necessariamente problematiche (x es.
l'uso di una variabile non definita)
E' possibile (in php.ini, opp attraverso la funzione error_reporting(..))
impostare il livello di "verbosità" dei messaggi di errore, x es con:
error_reporting = E_ALL
l'interprete mostra tutti i tipi di errori, warning, notice, ecc.
Elenco delle possiblità: in php.ini opp su Zimuel 2017, p. 73
[rif. Zimuel 2017 cap. 4, php.net/manual/en/language.exceptions.php]
Goy ‐ a.a. 2019/2020 Tecnologie Web: approcci avanzati 3
3
PHP: errori ed eccezioni ‐ II
In PHP è possibile gestire gli errori nel codice attraverso le
eccezioni:
try {
// codice che può dare un errore
// (generare un'eccezione);
} catch (Exception $e) {
// gestione dell'eccezione, x es:
echo "Attenzione: {$e->getMessage()}";
...
} finally {
// istruzioni da eseguire sempre
}
Esistono classi più specifiche per gestire tipi specifici di errori ed eccezioni…
[rif. php.net/manual/en/language.errors.php7.php]
[rif. php.net/manual/en/language.exceptions.php]
Goy ‐ a.a. 2019/2020 Tecnologie Web: approcci avanzati 4
4
2aa 2019/2020
PHP: errori ed eccezioni ‐ III
Le eccezioni possono essere generate da funzioni predefinite o
da funzioni definite dal programmatore, x es:
function inverse(int $x): float {
if (0 === $x) {
throw new Exception('Divisione per 0!');
}
}
per generare un'eccezione (cioè un oggetto di tipo Exception)
Su un oggetto di tipo Exception posso invocare diverse funzioni,
per ottenere info sull'errore, per es:
$e->getMessage();
$e->getCode();
$e->getFile();
$e->getLine();
$e->getTrace(); //istruzioni che hanno generato l'eccezione
$e->getTraceAsString();
$e->__toString();
Goy ‐ a.a. 2019/2020 Tecnologie Web: approcci avanzati 5
5
Interazione con i
database in PHP
Goy ‐ a.a. 2019/2020 Tecnologie Web: approcci avanzati 6
6
3aa 2019/2020
PHP: interazione con database ‐ I
Per interagire con un DBMS da un programma (script) PHP:
1. Aprire una connessione con il Database Server (DBMS)
e selezionare un database
2. Inviare al DBMS una query SQL (che il DBMS eseguirà sul
database selezionato)
3. Eventualmente, estrarre (ed elaborare/visualizzare) i
dati contenuti nel risultato della query (recordset)
4. Chiudere la connessione
Prima di vedere come si fa, costruiamoci un database per il
nostro CASE STUDY (quiz), utilizzando MySQL Server/MariaDB
dal pannello di XAMPP
• avviate il DB Server
• accedete alla User Interface
del DBMS (PhpMyAdmin)
Goy ‐ a.a. 2019/2020 Tecnologie Web: approcci avanzati 7
7
PHP: interazione con database ‐ II
Da phpMyAdmin, potete (tra le altre cose):
• controllare gli utenti abilitati ad accedere al DB Server,
cliccando su Privilegi
NB: la configurazione di default di XAMPP prevede, su localhost,
un utente root, senza password (che non è una configurazione
sicura, ma in fase di sviluppo va bene…)
• creare un nuovo database, cliccando su Database
Goy ‐ a.a. 2019/2020 Tecnologie Web: approcci avanzati 8
8
4aa 2019/2020
PHP: interazione con database ‐ III
• esportare/importare un database in forma di query SQL
(salvata in un file di testo),
selezionando il database, cliccando su Esporta e salvando
il risultato in un file (es. myDatabase.sql), oppure
cliccando su Importa e selezionando il file contenente la
query (es. myDatabase_save25122015.sql)
Creiamo un database (domande_quiz) che contiene le domande
del nostrio quiz:
Tabella domande, campi: Tabella risposte, campi:
▫ id (autoincrement) ▫ id_risp (autoincrement)
▫ testo (text) ▫ testo_risp (varchar)
▫ punti (int) ▫ dom_rif (int)
▫ tipo (varchar/string) ▫ giusta (boolean)
+ vincolo di integrità referenziale tra risposte.dom_rif e domande.id
... e lo popoliamo:
Goy ‐ a.a. 2019/2020 Tecnologie Web: approcci avanzati 9
9
Il database domande_quiz ‐ I
domande risposte
id testo punti tipo obbl id_ testo_risp dom giusta
risp _rif
1 Come si 2 text true
chiama il 1 kit 1 true
figlio di Tex? 2 capelli_d_argento 2 true
2 Qual è 4 radio true 3 nuvola_bianca 2 false
il nome
indiano di 4 vecchio_lupo 2 false
Carson? 5 navajos 3 true
3 A quale 3 drop‐ true 6 comanche 3 false
tribù down
di indiani 7 apache 3 false
appartiene 8 el_morisco 4 true
Tiger Jack?
9 pat_mac_ryan 4 true
4 Quali dei 5 check false
seguenti sono box 10 mefisto 4 false
amici storici 11 clark_kent 4 false
di Tex?
RIF domande_quiz.sql
Goy ‐ a.a. 2019/2020 Tecnologie Web: approcci avanzati 10
10
5aa 2019/2020
PHP: interazione con database ‐ IV
...
Goy ‐ a.a. 2019/2020 Tecnologie Web: approcci avanzati 11
11
PHP: interazione con database ‐ V
In PHP, per interagire con un DBMS possiamo usare due librerie
(object oriented):
• PDO (PHP Data Objects)
• MySQLi
Goy ‐ a.a. 2019/2020 Tecnologie Web: approcci avanzati 12
12
6aa 2019/2020
PHP: interazione con database ‐ VI
Per interagire con il nostro database usiamo la libreria PDO;
Vediamo il dettaglio dei vari passi:
1. Aprire una connessione con il Database Server (DBMS) e
selezionare un database
$db = new PDO("mysql:dbname=domande_quiz;host=localhost",
"root", "" );
Data Source Name:
username e password ‐ DBMS usato (mysql)
di un utente accreditato ‐ nome del DB (domande_quiz)
‐ server su cui gira il DBMS Server
(localhost)
Goy ‐ a.a. 2019/2020 Tecnologie Web: approcci avanzati 13
13
PHP: interazione con database ‐ VII
2. Inviare al DBMS una query SQL (che il DBMS eseguirà sul
database selezionato)
Se leggiamo (SELECT...):
$resultSet = $db->query("SELECT * FROM risposte
WHERE dom_rif=2");
oggetto di tipo PDOStatement, contenente i risultati
(recordset), oppure false (se la query fallisce)
Se scriviamo (INSERT, DELETE, UPDATE...):
$resultDel = $db->exec("DELETE FROM domande
WHERE tipo='checkbox'");
numero di righe interessate dall'operazione, oppure false
(se la query fallisce)
NB si può anche usare il metodo query per inviare una
INSERT/DELETE/UPDATE... in quel caso il risultato è true se la
query va a buon fine (false altrimenti)
Goy ‐ a.a. 2019/2020 Tecnologie Web: approcci avanzati 14
14
7aa 2019/2020
PHP: interazione con database ‐ VIII
Attenzione!!
Quando includete in una query SQL dei dati ricevuti dal
client (es. dati che arrivano da un form) non dimenticate di
validare l'input (controllare i valori dei parametri prima di
usarli) per evitare iniezioni SQL!!
A questo scopo è possibile usare la funzione
quote(string) safe string; x es:
$safeRispUt = quote($_POST["risp_utente"]);
$res = $db->query("SELECT * FROM risposte
WHERE testo_risp=$safeRispUt");
Goy ‐ a.a. 2019/2020 Tecnologie Web: approcci avanzati 15
15
PHP: interazione con database ‐ IX
3. Eventualmente, estrarre (ed elaborare/visualizzare) i dati
contenuti nel risultato della query (recordset)
Il risultatodi una SELECT è un oggetto (un PDOStatement) =
array ($resultSet) i cui elementi sono array associativi
(chiavi = campi della tabella, valori = valori delle celle):
id_risp testo_risp dom_rif giusta
2 capelli_d_argento 2 true $resultSet[0]
3 nuvola_bianca 2 false $resultSet[1]
4 vecchio_lupo 2 false $resultSet[2]
foreach ($resultSet as $record){
// do something with $record }
ad ogni passo la variabile $record conterrà una riga del risultato,
da cui potrò leggere i vari valori, x es:
$record["testo_risp"] capelli_d_argento/nuvola_bianca/vecchio_lupo
$record["giusta"] true/false/false
Goy ‐ a.a. 2019/2020 Tecnologie Web: approcci avanzati 16
16
8aa 2019/2020
PHP: interazione con database ‐ X
4. Chiudere la connessione
$db = NULL;
Se la connessione non viene chiusa esplicitamente,
l'interprete la chiude quando temina lo script, ma è
considerata buona pratica inserire un'esplicita istruzione
di chiusura, quando le operazioni sul database sono
terminate...
Goy ‐ a.a. 2019/2020 Tecnologie Web: approcci avanzati 17
17
PHP: interazione con database ‐ XI
Gestione degli errori
• nell'interazione con un DBMS è facile che qualcosa vada storto
(la connessione al DB Server, la query, ...) è importante
gestire i possibili errori
• il modo migliore è attraverso il meccanismo delle eccezioni, x es:
try {
// istruzioni di connessione al DB
} tipo di eccezione
catch (PDOException , $ex) { da catturare
// istruzioni di gestione dell'errore
?>
Errore (DB):aa 2019/2020
PHP: interazione con database ‐ XII
E' buona pratica mettere la gestione della connessione al DBMS
in un file separato, importato in tutte i file PHP che accedono al
DB; per es. in connDB.php:
$erroreDB = "";
try {
$db = new
PDO("mysql:dbname=domande_quiz;host=localhost",
"root", "" );
}
catch (PDOException $ex) {
$erroreDB = $ex->getMessage();
}
e in pagina.php:
require("connDB.php");
if ($erroreDB != "") {
echo $erroreDB;
}
Goy ‐ a.a. 2019/2020 Tecnologie Web: approcci avanzati 19
19
PUT ALL TOGETHER & TRY YOURSELF!
CASE STUDY: quiz (versione 3)
Aggiorniamo il case study
• leggiamo le domande (del form) dal database
– importate in MySQL (tramite PhMyAdmin) domande_quiz.sql
– avete, in linea di massima, almeno due strade alternative:
(a) continuare ad usare la classe Domanda, modificandola (per es.
creando una nuova classe Risposta che mi dice anche se è giusta o no...);
prendo dal DB le info con cui costruisco le istanze di Domanda...
(b) abbandonare la classe Domanda e proseguire meno object‐oriented
prendo direttamente dal DB le info da mostrare sulla pagina...
NB il caso delle checkbox (gestite con array) è complesso...
provate magari prima senza checkbox!
Ma... esiste in PHP una funzione, array_diff, che confronta due (o +)
array e restituisce un array con le chiavi e i valori del primo array che
non sono presenti negli altri array (quindi se due array sono uguali,
restituisce ‐ in entrambi i possibili modi di confrontarli ‐ un array vuoto!)
RIF DomandaIII.php,
Goy ‐ a.a. 2019/2020connDB.php, RispostaIII.php,
domande_v3.php, Tecnologie quiz_v3.php,
Web: approcci avanzati
quiz_v3_elabora_risposte.php 20
20
10aa 2019/2020
saltato slide 21‐32
Gestire le sessioni
in PHP
Goy ‐ a.a. 2019/2020 Tecnologie Web: approcci avanzati 21
21
Sessioni ‐ I
• Il protocollo HTTP è stateless, cioè non memorizza lo stato
di una conversazione client‐server due richieste
successive dello stesso client allo stesso server sono
trattate indipendentemente (e non come un'unica
"conversazione")
• A volte, però, è utile che il server abbia "memoria" dei passi
precedenti nella conversazione con un client...
• Il principale meccanismo utilizzato dai Web Server per
mantenere "memoria" della conversazione con un client è
la sessione
Goy ‐ a.a. 2019/2020 Tecnologie Web: approcci avanzati 22
22
11aa 2019/2020
Sessioni ‐ II
Sessione = serie di accessi ad un sito sessione1 utente1
web, effettuati da uno stesso client, sito sessione2 utente2
in un arco di tempo delimitato, web
durante il quale viene mantenuto sessione3 utente3
uno stato dell'interazione ecc… ecc…
• Inizio di una sessione: il Web Server crea automaticamente un
"oggetto" sessione, con ID univoco (session ID), per ogni client
che si connette al sito web
• Fine di una sessione:
quando scade (timeout) ‐ vedi configuraz. del Web Server
quando viene esplicitamente dato un comando di "fine
sessione" (per esempio l'utente clicca su "logout" o "esci")
quando viene chiuso il browser
• Visto che HTTP è stateless... la sessione serve a mantenere
traccia di una "conversazione" tra client e server
Goy ‐ a.a. 2019/2020 Tecnologie Web: approcci avanzati 23
23
Sessioni ‐ III
La sessione è generalmente gestita attraverso i cookies di
sessione (session cookies)
Cookies = dati (di tipo testuale) che il server salva sul
client (ogni browser salva i cookies... a modo suo!)
a. quando un browser contatta un server per richiedere una
risorsa (es. homepage), il server invia la risorsa + un session
cookie (nel campo set‐cookie nell'HTTP response)
b. in ogni successiva richiesta, il client invierà, nella richiesta,
anche il session cookie (nel al campo cookie nell'HTTP
request), che viene così letto dal server
c. quando la sessione scade o viene chiusa, il cookie viene
distrutto
(dal server) HTTP request
(campo cookie)
HTTP HTTP client
Server HTTP response
(campo set‐cookie)
Goy ‐ a.a. 2019/2020 Tecnologie Web: approcci avanzati 24
24
12aa 2019/2020
Sessioni ‐ IV
• un session cookie contiene il session ID e l'identificativo del
server che lo ha prodotto (un server può leggere solo i cookies
che lui stesso ha scritto!)
• eventuali altri dati sulla sessione sono salvati server‐side,
tipicamente in una tabella associativa (la gestione delle sessioni
è fatta con un approccio ibrido client‐side session cookies +
server‐side tabella associativa dei dati legati alla sessione)
session ID 1 dati sulla sessione 1
session ID ... dati sulla sessione ...
session ID n dati sulla sessione n
Nota: le informazioni sulla sessione (sessionID, ecc.) vengono
salvate (sul server) nella cartella indicata nel file php.ini:
session.save_path = "${path}\tmp\"
la cartella C:\xampp\tmp deve esistere ed essere scrivibile!
Goy ‐ a.a. 2019/2020 Tecnologie Web: approcci avanzati 25
25
Sessioni in PHP ‐ I
session_start(); funzione PHP che:
• verifica se c'è già una sessione attiva (cioè se c'è un
sessionID in un session cookie inviato dal client)
• se non lo trova ne crea uno e crea una entry nella tabella
server‐side
• se lo trova, carica i dati relativi a quella sesssione (a quel
session ID)
anche se è controintuitivo, session_start() deve essere
invocata ogni volta che si vuole accedere a informazioni sulla
sessione!
Attenzione!
session_start() invia al client le info nell'intestazione
(header) di HTTP response va invocata prima che il
contenuto (body) di HTTP response venga generato, cioè
all'inizio della pagina (prima di qualunque altra cosa, anche
di uno spazio bianco)!!!
Goy ‐ a.a. 2019/2020 Tecnologie Web: approcci avanzati 26
26
13aa 2019/2020
Sessioni in PHP ‐ II
Tutti i dati relativi alla sessione sono reperibili nell'array
associativo superglobale $_SESSION
In particolare $_SESSION contiene le variabili di sessione
= variabili "globali al sito", cioè accessibili (visibili) da tutte le
pagine del sito, all'interno di una sessione (a differenza delle
variabili "normali" la cui visibilità è limitata alla singola pagina)
Per es:
session_start(); leggo lo username (x
... es da un form di login)
$_SESSION["user"] = $_POST["login"];
lo scrivo in una variabile di sessione (user)
Le variabili di sessione sono salvate sul server (come dati
associati a un certo session ID)
Goy ‐ a.a. 2019/2020 Tecnologie Web: approcci avanzati 27
27
Sessioni in PHP ‐ III
In tutte le pagine successive (visitate dopo aver inizializzato la
variabile di sessione) sarà possibile leggerne il valore
NB: se questo non è possibile, significa che la sessione è
scaduta!
Per es:
session_start();
...
if ( isset($_SESSION["user"]) ) {
//sessione valida
... funzione che restituisce true se la
} else { variabile (passata come parametro)
//sessione scaduta esiste (ed è stata inizializzata),
... false altrimenti
}
Goy ‐ a.a. 2019/2020 Tecnologie Web: approcci avanzati 28
28
14aa 2019/2020
Sessioni in PHP ‐ IV
possiamo usare le variabili di sessione per due scopi
principali:
1) per controllare gli accessi
2) per rendere delle informazioni disponibili nelle pagine
successive
1) Controllo degli accessi:
– login inizializzo una variabile di sessione
– pagine successive se la variabile è "settata", allora la
sessione è valida; se non lo è, significa che la sessione è
scaduta
se l'utente cerca di accedere ad una pagina del sito
senza passare dal login, la variabile di sessione non
verrà settata e l'accesso sarà impossibile!
Goy ‐ a.a. 2019/2020 Tecnologie Web: approcci avanzati 29
29
Sessioni in PHP ‐ V
2) Rendere informazioni disponibili nelle pagine successive:
– login inizializzo una variabile di sessione
– pagine successive il contenuto di tale variabile è sempre
disponibile
se voglio avere disponibile lo username in ogni pagina,
basta metterlo in un variabile di sessione!
Ho delle alternative per passare delle informazioni da una
pagina all'altra?
• se passo da una form:
• se passo cliccando su un link:
Goy ‐ a.a. 2019/2020 Tecnologie Web: approcci avanzati 30
30
15aa 2019/2020
Sessioni in PHP ‐ VI
Per chiudere una sessione (per es. quando l'utente clicca su
"logout"):
session_unset(); resetta le variabili di sessione
session_destroy(); distrugge la sessione (il session ID)
Se la sessione viene chiusa in modo meno esplicito (x es. perché
l'utente chiude il browser) al server NON viene notificata la fine della
sessione, quindi i dati server‐side non vengono cancellati
Dopo un certo tempo (configurabile in php.ini) di inattività su tali
dati, il server considera chiusa la sessione e li distrugge
Goy ‐ a.a. 2019/2020 Tecnologie Web: approcci avanzati 31
31
PUT ALL TOGETHER & TRY YOURSELF!
CASE STUDY: quiz (versione 4)
Aggiorniamo il case study
• usiamo una variabile di sessione per controllare gli accessi alla
nostra applicazione
– quiz_v4.php chiedo il nome all'utente
– quiz_v4_elabora_risposte.php leggo il nome (se non vuoto) e
setto una variabile di sessione; controllo se la variabile di sessione
è settata e solo se lo è procedo ad elaborare le risposte
NB l'impostazione della variabile di sessione e il successivo
controllo (funzione isset(...)) andrebbero fatti in due pagine
diverse!!
• inoltre potete aggiungere l'uso del campo obbl (che dice se una
domanda è obbligatoria), x es segnalandolo con un asterisco (e
rendendo required il campo del form)...
RIF DomandaIV.php,
Goy ‐ a.a. 2019/2020connDB.php, RispostaIV.php,
domande_v4.php, Tecnologie quiz_v4.php,
Web: approcci avanzati
quiz_v4_elabora_risposte.php 32
32
16Puoi anche leggere