L'estensione MySQLi per l'interazione tra PHP e MYSQL
1. Configurazione per l'interfaccia ai database
MySQLi è l'abbreviazione di MySQL improveded ("perfezionato") ed
è anche il nome di un'estensione per il linguaggio PHP, essa è stata realizzata
per mettere a disposizione degli sviluppatori delle funzionalità più avanzate
rispetto a quelle messe a disposizione dall'estensione MySQL per l'interazione
tra le applcazioni Web based e il noto DBMS Open Source.
L'estensione MySQLi è stata introdotta nella release 4.1.2 di PHP e
permette di sfruttare in modo semplice e veloce alcune nuove funzionalità messe
a dispozione dalle versioni più recenti del Database Manager MySQL a partire
dalla 3.2.2 fino alle più aggiornate 5.x.
Utilizzare questo strumento è molto semplice, la
libreria che ne permette il funzionamento, denominata php_mysqli.dll, è infatti disponibile nativamente
all'interno della cartella contenente le estensioni per PHP e sarà subito
utilizzabile nei sistemi Linux; per attivarla
inWindows, sarà invece sufficiente aggiungere nel
file PHP.ini la seguente direttiva all'elenco
denominato "Windows Extensions" o decommentarla se già presente:
extension=php_mysqli.dll
E'
buona norma che questa direttiva sia posta di seguito a quelle già presenti per
l'interazione con i database, in modo da non generare confusione; una volta
salvate le modifiche effettuate, basterà riavviare il Web server per fruire
delle funzionalità messe a disposizione da MySQLi.
Ma perché utilizzare questa estensione invece della
classica estensione MySQL utilizzata in milioni di applicazioni? In realtà non
è possibile sostenere in maniera assoluta che MySQLi sia preferibile rispetto
alla sua alternativa più classica, in molti sostengono addirittura che si
tratti di un progetto ancora incompleto e non ben supportato; grazie a MySQLi
vi sono però degli indubbi vantaggi che meritano di essere sottolineati:
- può essere utilizzata sia
all'interno di applicazioni realizzate seguendo il paradigma procedurale che quello Orientato agli Oggetti;
- fornisce il supporto nativo
al protocollo binario di MySQL introdotto con la versione 4.1;
- supporta stored procedures, query
multiple e transactions;
- permette impostazioni
avanzate per la connesssione tramite mysqli_init();
- supporta le prepared statements per il caching delle interrogazioni;
- garantisce prestazioni più
elevate dell'estensione MySQL, è ritenuta più sicura e fornisce in genere
migliori risposte in fase di debugging.
Come
anticipato, gli strumenti forniti da MySQLi possono essere impiegati sia
all'interno di applicazioni il cui codice è stato realizzato secondo il
paradigma procedurale che in uno script creato grazie all'Object-Oriented Programming; infatti, come si vedrà a
breve nel dettaglio, la gran parte delle funzioni messe a disposizione da
questa estensioni possono essere sostituite da un metodo concepito per uno
scopo analogo.
Naturalmente, anche le funzioni dell'estensione MySQL possono essere inserite all'interno di classi, ma la differenza sostanziale sta nel fatto i metodo di MySQli vengono forniti nativamente.
Naturalmente, anche le funzioni dell'estensione MySQL possono essere inserite all'interno di classi, ma la differenza sostanziale sta nel fatto i metodo di MySQli vengono forniti nativamente.
Le funzioni dell'estensione MySQLi sono state
concepite per rendere questo strumento il più possibile compatibile con
l'estensione MySQL; nella maggior parte dei casi è infatti possibile ritrovare
le funzioni classiche con una "i" finale aggiunta in coda al nome:
per esempio,mysql_connect() è stata così "tradotta"
in mysqli_connect() mentre mysql_query() è diventata mysqli_query().
Ciò nonostante è opportuno sottolineare che, al di là delle somiglianze relative al nome, non tutte le funzioni di MySQLi possono essere utilizzare nello stesso modo di quelle fornite da MySQL.
Ciò nonostante è opportuno sottolineare che, al di là delle somiglianze relative al nome, non tutte le funzioni di MySQLi possono essere utilizzare nello stesso modo di quelle fornite da MySQL.
2. Connessione a MySQL con MySQLi
Per la connessione tra
un'applicazione Web based realizzata in PHP e un Database Manager MySQL tramite
l'estensione MySQLi, sono disponibili due procedure, una basata sul paradigma
procedurale, la seconda basata invece sull'approccio per oggetti.
Nel primo caso la connessione avviene per funzione, nel caso della OOP essa avviene invece per istanza.
Nel primo caso la connessione avviene per funzione, nel caso della OOP essa avviene invece per istanza.
La connessione effettuata utilizzando
la programmazione procedurale si basa su una funzione specifica
denominata mysqli_connect() che accetta
come parametri i seguenti dati:
- hostname: il nome di Rete della macchina ospitante il
Database server, ad esempio un indirizzo IP o "localhost" nel
caso di installazioni locali;
- username: il nome dell'utente da utilizzare per la
connessione, esso dovrà avere i privilegi necessari per l'accesso e la
manipolazione dei dati;
- password: la parola chiave necessaria per
l'autenticazione dell'utente che si desidera utilizzare in connessione;
- database: il nome del database che si desidera
interfacciare alla propria applicazione.
I più accorti si saranno
immediatamente resi conto di un'importante differenza tra le funzioni
mysqli_connect() e mysql_connect(), la seconda infatti non accetta come
parametro il nome della base di dati da selezionare, a questo scopo è infatti
destinata la funzione mysql_select_db().
MySQLi mette a disposizione una funzione omologa, denominata non a casomysqli_select_db(), che però deve essere utilizzata esclusivamente nel caso in cui si presenti la necessità di modificare il database predefinito (cioè quello selezionato tramite mysqli_connect()).
Un esempio di connessione tramite approccio procedurale potrebbe essere il seguente:
MySQLi mette a disposizione una funzione omologa, denominata non a casomysqli_select_db(), che però deve essere utilizzata esclusivamente nel caso in cui si presenti la necessità di modificare il database predefinito (cioè quello selezionato tramite mysqli_connect()).
Un esempio di connessione tramite approccio procedurale potrebbe essere il seguente:
<?php
// connessione a MySQL con mysqli_connect()
// definizione delle variabili
$host = "localhost";
$user = "username";
$pass = "password";
$db = "data";
// connessione al DBMS
$conn = @mysqli_connect($host, $user, $pass, $db)
or die(mysqli_connect_error());
?>
mysqli_connect_error() è una funzione apposita per
notificare eventuali malfunzionamenti in fase di connessione (ad esempio: un
errore di autenticazione).
Per quanto riguarda invece le
connessioni tramite approccio per oggetti, è stato anticipato che in questo
caso il fulcro della procedura è basato essenzialmente su un'istanza:
<?php
// connessione a MySQL per istanza
// definizione delle variabili
$host = "localhost";
$user = "username";
$pass = "password";
$db = "data";
// connessione al DBMS
$conn = @new mysqli($host, $user, $pass, $db);
if( mysqli_connect_errno())
{
die(mysqli_connect_error());
}
?>
Nel esempio proposto, viene
effettuata un'istanza dell'oggetto "$conn" appartenente alla classe
"mysqli"; come è possibile osservare, questa operazione prevede il
passaggio degli stessi parametri previsti per la funzione mysqli_connect().
Nel codice precedente viene introdotta anche un'altra funzione, mysqli_connect_errno()che ha il compito di produrre, in caso di malfunzionamento, il numero identificativo dell'errore notificato in connessione dal Database manager; se questo numero dovesse essere generato, allora la funzione mysqli_connect_error() comunicherà all'utente la tipologia di eccezione verificatasi.
Nel codice precedente viene introdotta anche un'altra funzione, mysqli_connect_errno()che ha il compito di produrre, in caso di malfunzionamento, il numero identificativo dell'errore notificato in connessione dal Database manager; se questo numero dovesse essere generato, allora la funzione mysqli_connect_error() comunicherà all'utente la tipologia di eccezione verificatasi.
Per la chiusura di una
connessione, l'estensione MySQLi mette a disposizione la funzionemysqli_close() che accetta come parametro il link
alla connessione che si desidera chiudere, nel caso in cui sia attiva un'unica
connessione non sarà necessario passarne il link alla funzione.
In alternativa, nel caso dell'approccio OOP, sarà possibile utilizzare il metodomysqli::close() come istanza della classe di connessione:
In alternativa, nel caso dell'approccio OOP, sarà possibile utilizzare il metodomysqli::close() come istanza della classe di connessione:
// chiusura di una connessione con il metodo mysqli::close()
@$conn->close();
3. Connessione con mysqli_real_connect() e il metodo
real_connect()
La funzione mysqli_connect() e l'istanza alla classe
di connessione non sono le uniche soluzioni disponibili per l'accesso al
Database manager MySQL messe a disposizione da MySQLi.
In alternativa, è possibile utilizzare la funzione mysqli_real_connect() o il relativo metodo mysqli::real_connect; la funzione mysqli_real_connect() funziona in modo molto simile a mysqli_connect() per aprire una connessione al DBMS, ma presenta come differenza sostanziale la possibilità di specificare dei parametri addizionali (Flags).
In alternativa, è possibile utilizzare la funzione mysqli_real_connect() o il relativo metodo mysqli::real_connect; la funzione mysqli_real_connect() funziona in modo molto simile a mysqli_connect() per aprire una connessione al DBMS, ma presenta come differenza sostanziale la possibilità di specificare dei parametri addizionali (Flags).
I parametri addizionali previsti per questa funzione
sono cinque e rappresentano altrettante opzioni di connessione:
- MYSQLI_CLIENT_COMPRESS: permette l'utilizzo del
protocollo di compressione;
- MYSQLI_CLIENT_FOUND_ROWS: restituisce il numero di
record rilevati, non quello dei record coinvolti dall'interrogazione;
- MYSQLI_CLIENT_IGNORE_SPACE: consente l'utilizzo di
spazi vuoti dopo i nomi delle funzioni e permette di rendere riservati
tutti i nomi delle funzioni;
- MYSQLI_CLIENT_INTERACTIVE: attiva l'impostazione di
MySQLinteractive_timeout espressa in secondi
invece di wait_timeout (sempre
espressa in secondi), in questo modo la connessione verrà chiusa dopo
l'intervallo di tempo definito in mancaza di istruzioni al DBMS;
- MYSQLI_CLIENT_SSL: utilizza il protocollo
crittografico SSL (Secure Sockets Layer) che consente una
comunicazione sicura e l'integrità dei dati su reti TCP/IP.
Per
questioni di sicurezza, la funzione mysqli_real_connect() non supporta il flagMULTI_STATEMENT per l'invio simultaneo di più
interogazioni al DBMS, a questo scopo sarà invece possibile utilizzare come
alternativa una funzione apposita, denominatamysqli_multi_query() (o
il relativo metodo mysqli::multi_query).
L'utilizzo della funzione mysqli_real_connect()
all'interno di un contesto procedurale può essere riassunto nel seguente
esempio:
<?php
// connessione con il metodo
mysqli_real_connect()
// inizializzazione di MySQLi
$link = @mysqli_init();
// controllo sull'inizializzazione
if (!isset($link))
{
die("Errore nell'inizializzazione di MySQLi.");
}
// definizione delle variabili
$host = "localhost";
$user = "username";
$pass = "password";
$db = "data";
// connessione al DBMS
if (!mysqli_real_connect($link,
$host, $user, $pass, $db))
{
die("Errore in connessione (" . mysqli_connect_errno() .
") " . mysqli_connect_error());
}else{
echo "Connessione avvenuta con successo.";
}
// chiusura della connessione
@mysqli_close($link);
?>
Si
analizzi il codice proposto:
- viene inizializzato MySQLi
tramite la funzione mysqli_init() che
crea una risorsa ("link") da passare come argomento
all'istruzione di connessione;
- vengono definite le
variabili da utilizzare come parametri a mysqli_real_connect();
- viene stabilita la
connessione a meno di eventuali errori;
- viene chiusa la connessione
tramite la funzione mysqli_close() a cui viene passata come argomento la
risorsa creata in inizializzazione.
Si
analizzi ora la stessa procedura basata questa volta sul paradigma ad oggetti e
sul metodo mysqli::real_connect:
<?php
// connessione con il metodo
mysqli::real_connect
// inizializzazione di MySQLi
$mysqli = @mysqli_init();
// controllo
sull'inizializzazione
if (!isset($mysqli))
{
die("Errore nell'inizializzazione di MYSQLi.");
}
// definizione delle variabili
$host = "localhost";
$user = "username";
$pass = "password";
$db = "data";
// connessione al DBMS
if
(!$mysqli->real_connect($host, $user, $pass, $db))
{
die("Errore in connessione (" . mysqli_connect_errno() .
") " . mysqli_connect_error());
}else{
// notifica in caso di conessione avviata
echo "Connessione avvenuta con successo.";
}
// chiusura della connessione
@$mysqli->close();
?>
Le
differenze tra i due codici proposti non sono tante: anche in questo caso
MySQLi viene inizializzato tramite mysqli_init(), ma la risorsa creata non deve
essere passata al metodo di connessione come parametro, perché disponibile per
istanza all'interno della classe MySQLi; di conseguenza non sarà necessario
passare questo argomento neanche al metodo mysqli::close che chiuderà la
connessione.
4. Esecuzione delle query
L'estensione MySQLi mette a disposizione degli
sviluppatori che desiderano inviare delle query tramite le proprie
applicazioni, una funzione apposita, denominata mysqli_query()a cui
corrisponde il metodo mysqli::query; queste componenti accettano come
parametro un'istruzione espressa in linguaggio SQL e potranno essere utilizzati
all'interno di costrutti procedurali o basati sul paradigma OOP.
Il codice seguente mostra un esempio di utilizzo della
funzione mysqli_query() all'interno di un approccio procedurale:
<?php
// esecuzione di query con
mysqli_query
// connessione al DBMS
$link = @mysqli_connect("localhost",
"username", "password", "data");
// controllo sullo stato della
connessione
if (mysqli_connect_errno())
{
echo "Connessione fallita: " . die (mysqli_connect_error());
}
// query per la creazione di una
tabella
if ($result = @mysqli_query($link, "CREATE TABLE prova
(id INT(2), nome VARCHAR(50))"))
{
echo "Tabella creata con successo.";
}
// liberazione della memoria dal
risultato della query
@mysqli_free_result($result);
// chiusura della connessione
@mysqli_close($link);
?>
L'esempio
mostra come la funzione mysqli_query() funzioni esattamente come mysql_query()
per l'estensone MySQL, i parametri accettati sono infatti la risorsa prodotta
dalla procedura di connessione ("$link" in questo caso) e
l'interrogazione inviata al DBMS.
La funzione mysqli_free_result() è opzionale, ma svolge l'utile compito di liberare lo spazio di memoria occupato dal risultato di una query una volta che questo viene ottenuto.
La funzione mysqli_free_result() è opzionale, ma svolge l'utile compito di liberare lo spazio di memoria occupato dal risultato di una query una volta che questo viene ottenuto.
Si analizzi ora la stesso esempio proposto in
precedenza, ma "tradotto" utilizzando il paradigma orientato agli
oggetti:
<?php
// esecuzione di query con
mysqli_query
// connessione al DBMS per
istanza
$mysqli = @new
mysqli("localhost", "username", "password",
"data");
// controllo sullo stato della
connessione
if (mysqli_connect_errno())
{
echo "Connessione fallita: " . die (mysqli_connect_error());
}
// query per la creazione di una
tabella
if ($result =
@$mysqli->query("CREATE TABLE nuova_prova (id INT(2), nome VARCHAR(50))"))
{
echo "Tabella creata con successo.";
}
// liberazione della memoria dal
risultato della query
@$result->close();
// chiusura della connessione
@$mysqli->close();
?>
In questo caso la connessione
viene prodotta per istanza di una classe ("mysqli"); una volta
effettuato il controllo necessario per stabilire l'effettivo avvio della
connessione, è possibile procedere con l'esecuzione della query per la
creazione della tabella tramite il metodo mysql::query.
Eseguita la query, è possibile introdurre il metodo mysqli_result::close per liberare la memoria occupata dal risultato dell'interrogazione (in alternativa è possibile utilizzare i metodi equivalenti mysqli_result::free o mysqli_result::free_result), per poi passare alla chiusura della connessione tramite il metodo mysqli::close.
Eseguita la query, è possibile introdurre il metodo mysqli_result::close per liberare la memoria occupata dal risultato dell'interrogazione (in alternativa è possibile utilizzare i metodi equivalenti mysqli_result::free o mysqli_result::free_result), per poi passare alla chiusura della connessione tramite il metodo mysqli::close.
5. Estrazione dei record
Una volta eseguita una query, tramite l'estensione
MySQLi è possibile utilizzare alcune funzioni appositamente dedicate
all'estrazione dei record; in questa parte della trattazione verrà presa in
analisi la funzione mysqli_fetch_array() che
consente di visualizzare tutti i record coinvolti da una determinata
interrogazione; tale funzione, molto simile alla corrispondente mysql_fetch_array() dell'estensione MySQL, produce
un array accettando come parametro il risultato di una query; questo array può
essere di diverso tipo sulla base del secondo parametro passato a
mysqli_fetch_array():
- MYSQLI_NUM: genera un array numerico;
- MYSQLI_ASSOC: genera un array
associativo;
- MYSQLI_BOTH: genera simultaneamente un
array numerico e associativo.
Il
seguente esempio permette di analizzare l'utilizzo della funzione
mysqli_fetch_array() all'interno di un contesto procedurale.
<?php
// estrazione dei dati con
mysqli_fetch_array()
// connessione al database
$link = @mysqli_connect("localhost",
"username", "password", "data");
// controllo sullo stato della
connessione
if (mysqli_connect_errno())
{
echo "Connessione fallita: " . die (mysqli_connect_error());
}
// esecuzione della query
$query = "SELECT nome
FROM prova ORDER by id DESC";
$result = @mysqli_query($link,
$query);
// controllo sul numero dei
record coinvolti
if(@mysqli_num_rows($result)!=0)
{
// risultato sotto forma di array numerico
while($row =
mysqli_fetch_array($result, MYSQLI_NUM))
{
echo $row[0] . "<br>";
}
// risultato sotto forma di array asscociativo
while($row =
mysqli_fetch_array($result, MYSQLI_ASSOC))
{
echo
$row['nome'] . "<br>";
}
// risultato sotto forma di array numerico o associativo
while($row = mysqli_fetch_array($result,
MYSQLI_BOTH))
{
echo $row['nome'] . "<br>";
echo $row[0] . "<br>";
}
}
// liberazione della memoria dal
risultato della query
@mysqli_free_result($result);
// chiusura della connessione
@mysqli_close($link);
?>
I valori
presenti all'interno di un array prodotto tramite mysqli_fetch_array() potrà
essere sviluppato attraverso un ciclo; nel caso in cui il flag associato come
parametro alla funzione si MYSQLI_NUM, verrà prodotto un array di tipo numerico
in cui i valori presenti all'interno del vettore saranno indicizzati da
"0" a "n", dove "n" è l'ultimo numero indice dell'array;
nell'esempio proposto viene effettuata un'interrogazione che coinvolge un solo
campo, quindi l'unico indice disponibile sarà "0".
Nel caso in cui invece il secondo argomento della
funzione sia MYSQLI_ASSOC, verrà prodotto un array associativo in cui i valori
verranno indicizzati tramite il nome dei campi coinvolti dalla query; nel caso
dell'esempio proposto, vengono estratti unicamente i valori relativi al campo
"nome" della tabella "prova", per cui l'unico indice
presente nell'array associativo sarà appunto "nome".
MYSQLI_BOTH ("both" significa appunto in
lingua Inglese "entrambi"), produce un array numerico e associativo,
quindi sarà possibile sia riferirsi agli indici da "0" a "n" che a quelli che hanno come nome il nome dei
campi che forniscono i record tramite query.
Naturalmente, anche per la funzione mysqli_fetch
array() esiste un metodo corrispondente denominato mysqli_result::fetch_array; il codice seguente mostra
un esempio dell'utilizzo di questo metodo all'interno di un contesto orientato
agli oggetti:
<?php
// estrazione dei dati con il
metodo mysqli_result::fetch_array
// connessione al database per
istanza
$mysqli = @new mysqli("localhost",
"username", "password", "data");
// controllo sullo stato della
connessione
if (mysqli_connect_errno())
{
echo "Connessione fallita: " . die (mysqli_connect_error());
}
// esecuzione della query
$query = "SELECT nome
FROM prova ORDER by id DESC";
$result =
@$mysqli->query($query);
// controllo sul numero dei
record coinvolti
if(@$result->num_rows > 0)
{
// risultato sotto forma di array numerico
while($row =
$result->fetch_array(MYSQLI_NUM))
{
echo $row[0]
. "<br>";
}
// risultato sotto forma di array asscociativo
while($row =
$result->fetch_array(MYSQLI_ASSOC))
{
echo $row['nome'] . "<br>";
}
// risultato sotto forma di array numerico o associativo
while($row =
$result->fetch_array(MYSQLI_BOTH))
{
echo
$row['nome'] . "<br>";
echo $row[0] . "<br>";
}
}
// liberazione della memoria dal
risultato della query
@$result->close();
// chiusura della connessione
@$mysqli->close();
?>
A
livello funzionale, la differenza tra l'approccio procedurale e quello
orientato agli oggetti è veramente molto sottile; in questo secondo caso la
connessione avviene per istanza, a questo punto sarà possibile sottoporre la
query al metodo mysqli::query e passarla come parametro al metodo
mysqli_result::fetch_array che, sottoposto a ciclo while, mostrerà i risultati
come valori di array di tipo diverso (numerici o associativi) a seconda del
flag passato come secondo argomento alla funzione.
Nel primo esempio è stato effettuato un controllo sul
numero dei record coinvolti dalla query utilizzando la funzione mysqli_num_rows(), a questa funzione corrisponde un
metodo, denominato mysqli_result->num_rows,
che potrà essere utilizzato in applicazioni la cui costruzione segue il
paradigma object oriented, come nel secondo esempio
proposto.
Commenti
Posta un commento