Quando si accede a un database in PHP, abbiamo due scelte: MySQLi e PDO. Quindi cosa dovresti sapere prima di sceglierne uno? Le differenze, il supporto del database, la stabilità e le preoccupazioni relative alle prestazioni verranno delineate in questo articolo.
Se lavori spesso con i database in PHP, dovresti controllare la gamma di script e app utili sia per MySQLi che per PDO sul mercato Envato.
App DOP sul mercato EnvatoDOP | MySQLi | |
Supporto per database | 12 diversi driver | Solo MySQL |
API | OOP | OOP + procedurale |
Connessione | Facile | Facile |
Parametri nominati | sì | No |
Mappatura degli oggetti | sì | sì |
Dichiarazioni preparate (dalla parte del cliente) | sì | No |
Prestazione | Veloce | Veloce |
Procedura di archiviazione | sì | sì |
È un gioco da ragazzi per connettersi a un database con entrambi:
// PDO $ pdo = nuovo PDO ("mysql: host = localhost; dbname = database", "username", "password"); // mysqli, modo procedurale $ mysqli = mysqli_connect ('localhost', 'username', 'password', 'database'); // mysqli, modo orientato agli oggetti $ mysqli = new mysqli ('localhost', 'username', 'password', 'database');
Si prega di notare che questi oggetti / risorse di connessione saranno considerati esistenti attraverso il resto di questo tutorial.
Sia PDO che MySQLi offrono un'API orientata agli oggetti, ma MySQLi offre anche un'API procedurale, che facilita la comprensione dei nuovi arrivati. Se hai familiarità con il driver PHP MySQL nativo, troverai la migrazione all'interfaccia procedurale MySQLi molto più semplice. D'altra parte, una volta masterizzato PDO, puoi usarlo con qualsiasi database desideri!
Il vantaggio principale di PDO su MySQL è il supporto del driver del database. Al momento di questa scrittura, PDO supporta 12 driver diversi, contrario a MySQLi, che supporta Solo MySQL.
Per stampare un elenco di tutti i driver attualmente supportati da PDO, utilizzare il seguente codice:
var_dump (DOP :: getAvailableDrivers ());
Cosa significa questo? Bene, in situazioni in cui è necessario passare il progetto per utilizzare un altro database, PDO rende il processo trasparente. Così tutto ciò che dovrai fare è modificare la stringa di connessione e alcune query, se utilizzano metodi non supportati dal nuovo database. Con MySQLi, è necessario riscrivi ogni pezzo di codice - domande incluse.
Questa è un'altra caratteristica importante di PDO; i parametri di legame è notevolmente più facile di usare il binding numerico:
$ params = array (': username' => 'test', ': email' => $ mail, ': last_login' => time () - 3600); $ pdo-> prepare ('SELECT * FROM users WHERE username =: username AND email =: email AND last_login>: last_login'); $ Pdo-> execute ($ params);
... contrario al modo MySQL:
$ query = $ mysqli-> prepare ('SELECT * FROM utenti WHERE username =? AND email =? AND last_login>?'); $ query-> bind_param ('sss', 'test', $ mail, time () - 3600); $ Query-> execute ();
Il binding del parametro del punto interrogativo potrebbe sembrare più breve, ma non è flessibile come i parametri con nome, perché lo sviluppatore deve sempre tenere traccia dell'ordine dei parametri; si sente "hacky" in alcune circostanze.
Sfortunatamente, MySQLi non supporta i parametri denominati.
Sia PDO che MySQLi possono mappare i risultati agli oggetti. Ciò è utile se non si desidera utilizzare un livello di astrazione del database personalizzato, ma si desidera comunque un comportamento simile a quello di un ORM. Immaginiamo di avere un Utente
classe con alcune proprietà, che corrispondono ai nomi dei campi da un database.
class User public $ id; pubblico $ first_name; public $ last_name; informazioni sulla funzione pubblica () return '#'. $ this-> id. ':'. $ this-> first_name. ". $ this-> last_name;
Senza la mappatura degli oggetti, avremmo bisogno di riempire il valore di ogni campo (manualmente o tramite il costruttore) prima di poter usare il Informazioni()
metodo correttamente.
Questo ci consente di predefinire queste proprietà prima ancora che l'oggetto sia costruito! Per esempio:
$ query = "SELECT id, first_name, last_name FROM users"; // PDO $ result = $ pdo-> query ($ query); $ result-> setFetchMode (PDO :: FETCH_CLASS, 'User'); while ($ user = $ result-> fetch ()) echo $ user-> info (). "\ n"; // MySQLI, modo procedurale if ($ result = mysqli_query ($ mysqli, $ query)) while ($ user = mysqli_fetch_object ($ result, 'User')) echo $ user-> info (). "\ N "; // MySQLi, modo orientato agli oggetti if ($ result = $ mysqli-> query ($ query)) while ($ user = $ result-> fetch_object ('User')) echo $ user-> info () . "\ n";
Entrambe le librerie forniscono Sicurezza dell'iniezione SQL, a patto che lo sviluppatore li utilizzi nel modo in cui erano destinati (leggi: escaping / associazione parametri con istruzioni preparate).
Diciamo che un hacker sta cercando di iniettare un codice SQL malevolo attraverso il parametro di query HTTP "username" (GET):
$ _GET ['username'] = "'; DELETE FROM users; / *"
Se non riusciamo a evitarlo, sarà incluso nella query "così com'è" - eliminando tutte le righe dal file utenti
tabella (sia PDO che mysqli supportano più query).
// PDO, "manuale" che sfugge $ username = PDO :: quote ($ _ GET ['username']); $ pdo-> query ("SELECT * FROM users WHERE username = $ username"); // mysqli, "manual" che sfugge $ username = mysqli_real_escape_string ($ _ GET ['username']); $ mysqli-> query ("SELECT * FROM users WHERE username = '$ username'");
Come potete vedere, PDO :: citazione ()
non solo sfugge alla stringa, ma la cita anche. Dall'altro lato, mysqli_real_escape_string ()
uscirà solo dalla stringa; dovrai applicare le virgolette manualmente.
// PDO, istruzione preparata $ pdo-> prepare ('SELECT * FROM users WHERE username =: username'); $ pdo-> execute (array (': username' => $ _GET ['username'])); // mysqli, istruzioni preparate $ query = $ mysqli-> prepare ('SELECT * FROM users WHERE username =?'); $ query-> bind_param ('s', $ _GET ['username']); $ Query-> execute ();
Raccomando di utilizzare sempre istruzioni preparate con query vincolate anziché P
DO :: citazione ()
emysqli_real_escape_string ()
.
Mentre sia PDO che MySQLi sono abbastanza veloci, MySQLi ha prestazioni significativamente più veloci nei benchmark: ~ 2,5% per le dichiarazioni non preparate e ~ 6,5% per quelle preparate. Tuttavia, l'estensione nativa di MySQL è ancora più veloce di entrambi. Quindi, se hai davvero bisogno di spremere ogni singolo pezzetto di performance, questa è una cosa che potresti prendere in considerazione.
Alla fine, PDO vince questa battaglia con facilità. Con il supporto di dodici diversi driver di database (diciotto diversi database!) E parametri con nome, possiamo ignorare la piccola perdita di prestazioni e abituarci alla sua API. Dal punto di vista della sicurezza, entrambi sono sicuri fintanto che lo sviluppatore li usa come dovrebbero essere usati (leggi: dichiarazioni preparate).
Quindi, se stai ancora lavorando con MySQLi, forse è tempo di cambiare!