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 1
aa 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 2
aa 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 3
aa 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 4
aa 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 5
aa 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 6
aa 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 7
aa 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 8
aa 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 10
aa 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 11
aa 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 12
aa 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 13
aa 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 14
aa 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 15
aa 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 16
Puoi anche leggere