PHP: Object oriented - Errori ed eccezioni in PHP - eccezioni, interazione con i DB, sessioni

Pagina creata da Mattia Beretta
 
CONTINUA A LEGGERE
PHP: Object oriented - Errori ed eccezioni in PHP - eccezioni, interazione con i DB, sessioni
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
PHP: Object oriented - Errori ed eccezioni in PHP - eccezioni, interazione con i DB, sessioni
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
PHP: Object oriented - Errori ed eccezioni in PHP - eccezioni, interazione con i DB, sessioni
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