Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial
  • Lezione 46 di 58
  • livello intermedio
Indice lezioni

PHP: API per l'accesso al DB

Un confronto tra le principali API per l'accesso, tramite PHP, ad un database MySQL: ext/mysql, ext/mysqli e PDO_MySQL.
Un confronto tra le principali API per l'accesso, tramite PHP, ad un database MySQL: ext/mysql, ext/mysqli e PDO_MySQL.
Link copiato negli appunti

Una delle installazioni più comuni per lo sviluppo web è la cosiddetta piattaforma LAMP (Linux, Apache, MySQL, PHP), che utilizza un server web Apache per ospitare applicativi scritti in PHP, i quali a loro volta sfruttano un database MySQL. In realtà, la stessa installazione può avere luogo su sistemi Windows ed un'interfacciamento tra PHP e MySQL può essere impiegato in programmi non destinati al web ma finalizzati ad altri scopi. In questa lezione vedremo quali sono e come usare le principali API per accedere ad un database MySQL.

Panoramica sulle API disponibili

Prima di iniziare il nostro percorso, è necessario fare chiarezza sulle API disponibili:

  • ext/mysql: le API tradizionali, introdotte nella versione 2.0 del linguaggio e alla base di moltissimi applicativi tuttora al lavoro nel web. Sono deprecate dalla versione 5.5 di PHP;
  • ext/mysqli: la versione più moderna delle API precedenti. Introdotte in PHP 5.0 sono ricche di funzionalità: basate sul paradigma della programmazione a oggetti, più efficienti, dispongono i prepared statements e supportano molte altre funzionalità del DBMS, come le stored procedures e transazioni;
  • PDO_MySQL: è un'estensione che permette di fare interagire PHP con molti DBMS, non solo MySQL, per poter rendere il codice indipendente (e quindi riutilizzabile) rispetto alla tecnologia di memorizzazione dei dati che si usa.

La documentazione ufficiale del DBMS si esprime chiaramente: per i nuovi sviluppi è consigliato utilizzare l'estensione mysqli o PDO, mentre le API tradizionali mysql (essendo deprecate) dovrebbero essere utilizzate solo per necessità di manutenzione dei progetti più datati.

La diffusione delle vecchie API è così estesa anche nella cultura degli sviluppatori attuali, e tale problematica è così sottovalutata, che la documentazione del linguaggio PHP dedica una pagina apposita alla scelta delle API, confrontando le tre tecnologie sopra citate.

In questa sede vedremo, in brevi esempi, tutte queste API: mysqli e PDO come scelte primarie, e per completezza anche le funzioni dell'estensione mysql.

Codice di esempio

Tutti gli esempi presentati nel seguito mostrano le stesse fasi:

  • connessione al DBMS;
  • un'operazione di inserimento;
  • l'esecuzione di una query, con successiva lettura dei dati prelevati.

Lo script PHP avrà bisogno di collegarsi al database fornendo l'indirizzo di rete, credenziali di accesso di un account MySQL valido (username e password) ed il nome del database stesso.

Assumeremo, per comodità, che i dati appena indicati siano resi disponibili, in ognuno dei successivi esempi, con le seguenti variabili, da valorizzare in base alla propria configurazione:

$host = "...";
$user = "...";
$pass = "…";
$dbname = "…";

Il database conterrà una tabella sola, persone, la cui struttura può essere prodotta nel seguente modo:

CREATE TABLE `persone` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `nome` varchar(50) NOT NULL,
  `cognome` varchar(50) NOT NULL,
  `eta` tinyint(3) unsigned NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB;

Usare mysqli

$my = new mysqli($host, $user, $pass,$dbname);
if ($my->connect_errno) {
	echo "Errore in connessione al DBMS: ".$my->error;
        exit();
} else {
    // inserimento di una nuova riga
    $nome="Carlo";
    $cognome="Verdi";
    $eta=25;
    $stmt = $my->prepare("INSERT INTO persone(cognome, nome, eta) VALUES (?, ?, ?)");
    $stmt->bind_param('ssi',$nome,$cognome,$eta);
    $stmt->execute(); 
    echo "Ultimo ID generato: ".$my->insert_id;
    // query che preleva tutto
    $query="SELECT * FROM persone";
    $r=$my->query($query);
    while ($row = $r->fetch_assoc())
    {
    	printf("ID: %s  Name: %s", $row["id"],$row["cognome"]." ".$row["nome"]);
    }
    $r->close();
}

L'avvio all'interazione con il DBMS si ottiene con un oggetto di classe mysqli. Viene istanziato passando al costruttore i parametri di connessione e le credenziali di accesso.

Appena inizializzato, controlliamo se la connessione è avvenuta con successo, verificando il valore della proprietà connect_errno: in caso di errore, essa ne conterrà il codice numerico; se invece l'operazione è stata svolta con successo, sarà valorizzata 0.

Se il nostro script ha avuto accesso al DBMS, procediamo con l'inserimento, che avviene mediante prepared statement:

  • la query viene preparata scrivendo in SQL tutta la sua parte fissa, mentre i parametri variabili sono rimpiazzati da punti interrogativi (?). Tutto questo tramite il metodo prepare;
  • si usa il metodo bind_param per passare i parametri reali. Ne saranno accettati tanti quanti sono i punti interrogativi nello statement. Come primo argomento viene passata una stringa contenente un flag per ogni parametro: i flag specificano il tipo di dato del valore: s per string, i per integer, d per double e b per blob;
  • dopo il binding dei parametri, si passa all'esecuzione vera e propria, tramite il metodo execute.

Considerato che la tabella ha una chiave primaria intera generata in automatico con autoincremento, si potrà leggere l'ultimo id creato con il metodo insert_id.

Per le interrogazioni, si usa il metodo query cui si passa un comando SELECT completo. I risultati, nell'esempio, vengono letti iterativamente con fetch_assoc che per ogni record crea un array associativo, quindi consultabile usando i nomi dei campi come chiavi.

Oltre a fetch_assoc, esiste anche il metodo fetch_array che permette di ottenere ogni record non solo in modalità associativa ma anche in formato numerico, nonchè in entrambi i formati contemporaneamente. La scelta verrà indicata dal programmatore al momento di invocare il metodo tramite il parametro in input, da scegliere tra MYSQLI_NUM (numerico), MYSQLI_ASSOC (associativo), MYSQLI_BOTH (entrambi).

Un aspetto interessante di mysqli consiste nella possibilità di attivare le stesse funzionalità in modalità procedurale, usando quindi delle funzioni piuttosto che l'approccio a oggetti. Il primo dei due, dall'aspetto più “tradizionale”, potrebbe risultare più familiare a programmatori PHP non del tutto convertiti ancora al modello ad oggetti. Una comparazione è approfonditamente discussa in un'apposita pagina del manuale online di PHP.

PDO

try {
    $conn = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);
    // inserimento
    $nome="Carlo";
    $cognome="Verdi";
    $eta=25;
    $stmt = $conn->prepare("INSERT INTO persone(cognome, nome, eta) VALUES (:cognome, :nome, :eta)");
    $stmt->bindParam(':cognome', $cognome, PDO::PARAM_STR);
    $stmt->bindParam(':nome', $nome, PDO::PARAM_STR);
    $stmt->bindParam(':eta', $eta, PDO::PARAM_INT);
    $stmt->execute(); 
    echo "Ultimo ID generato: ".$conn->lastInsertId();
    // query
    $query = "SELECT * FROM persone";
    foreach ($conn->query($query) as $row) {
	print $row['id'] . "\t";
        print $row['nome'] . "\t";
        print $row['cognome'] . "\n";
    }
}
catch(PDOException $e)
{
    echo $query . "<br>" . $e->getMessage();
}

PDO, a differenza di mysqli non è espressamente orientato a MySQL ma è costituito da classi generiche potenzialmente adattabili a qualunque DBMS.

Nel codice precedente si istanzia un oggetto PDO, il cui costruttore riceve in input una stringa di connessione che specifica il tipo del DBMS, indirizzi di rete dell'istanza cui connettersi e credenziali di accesso.

Il codice PHP che ne deriva può essere riutilizzato indipendentemente dal DBMS a supporto. L'unico requisito è che esista un driver apposito che faccia da interprete tra PDO ed il tipo di database scelto.

Anche in questo esempio si è svolto un inserimento e subito dopo una query. La prima operazione ha richiesto l'uso di un prepared statement, come spiegato nel paragrafo precedente per mysqli. Si è pertanto invocato il metodo prepare che predispone un comando generico contenente la struttura base dell'INSERT che si vuole realizzare. Successivamente, con bindParam, si specificano i singoli parametri da utilizzare, per ognuno dei quali deve essere indicato il tipo di dato (in questo caso: PDO::PARAM_STR per le stringhe e PDO::PARAM_INT per i numeri interi). Infine, con execute si esegue lo statement.

L'interrogazione viene eseguita con il comando query ed il risultato è direttamente fruibile tramite un ciclo foreach. Come si vede ogni record potrà essere letto specificando, in modalità associativa, i nomi dei campi.

Estensione mysql

Le funzioni che fanno parte dell'estensione mysql di PHP sono tuttora impiegate in tantissimi applicativi.

$r = mysql_connect($host, $user, $pass);
if (!$r) {
    echo "Could not connect to server\n";
    exit();
} else {
    mysql_select_db($dbname);
    // inserimento
    $insert="INSERT INTO persone(cognome, nome, eta) VALUES ('Carlo', 'Verdi', 25)";
    mysql_query($insert);
    echo "Ultimo ID generato: ".mysql_insert_id();
    // query
    $query="SELECT * FROM persone";
    $r=mysql_query($query);
    while ($row = mysql_fetch_array($r, MYSQL_ASSOC))
    {
    	printf("ID: %s  Name: %s", $row["id"],$row["cognome"]." ".$row["nome"]);echo "\n";
    }
    mysql_free_result($r);
}
mysql_close();

Come si vede, in questo caso l'approccio è totalmente procedurale. L'esempio mostra delle funzioni che ricordano molto i metodi impiegati nel precedente esempio di mysqli:

  • mysql_connect: permette di connettersi al DBMS utilizzando le credenziali indicate;
  • mysql_select_db: indica quale database si vuole utilizzare tra quelli a disposizione del profilo di connessione;
  • mysql_query: offre la possibilità di inviare sia comandi di modifica che normali interrogazioni;
  • mysql_fetch_array: consente di visionare uno alla volta i record ottenuti tramite la query. Il parametro passato in input indica che l'accesso avverrà in maniera associativa: ogni record verrà fornito sotto forma di array, le cui chiavi avranno lo stesso nome dei campi della tabella;
  • mysql_free_result: libera la memoria dalle risorse utilizzate dai risultati della query;
  • mysql_close: chiude la connessione.

Come spiegato nella documentazione ufficiale e già ricordato all'inizio di questa lezione, tali funzioni sono state deprecate a partire da PHP 5.5, e quindi non dovrebbero più essere utilizzate in nuovi progetti.

Ti consigliamo anche