PDO versus MySQLi welke moet u gebruiken?

Bij het openen van een database in PHP hebben we twee keuzes: MySQLi en PDO. Dus wat moet je weten voordat je er een kiest? De verschillen, databasesteun, stabiliteit en prestatieproblemen worden in dit artikel geschetst.

Als u vaak in PHP met databases werkt, wilt u misschien het bereik van nuttige scripts en apps voor zowel MySQLi als PDO bekijken op Envato Market.

PDO-apps op Envato Market

Samenvatting

BOB MySQLi
Databaseondersteuning 12 verschillende stuurprogramma's MySQL alleen
API OOP OOP + procedure
Verbinding Gemakkelijk Gemakkelijk
Benoemde parameters Ja Nee
Objecttoewijzing Ja Ja
Voorbereide verklaringen
(kant van de cliënt)
Ja Nee
Prestatie Snel Snel
Opgeslagen procedures Ja Ja

Verbinding

Het is een makkie om verbinding te maken met een database met beide:

// PDO $ pdo = nieuwe PDO ("mysql: host = localhost; dbname = database", 'gebruikersnaam', 'wachtwoord'); // mysqli, procedurele weg $ mysqli = mysqli_connect ('localhost', 'gebruikersnaam', 'wachtwoord', 'database'); // mysqli, object georiënteerde manier $ mysqli = new mysqli ('localhost', 'gebruikersnaam', 'wachtwoord', 'database');

Houd er rekening mee dat deze verbindingsobjecten / -bronnen worden geacht te bestaan ​​door de rest van deze zelfstudie.


API-ondersteuning

Zowel PDO als MySQLi bieden een objectgeoriënteerde API, maar MySQLi biedt ook een procedurele API - waardoor het voor nieuwkomers gemakkelijker wordt om dit te begrijpen. Als u bekend bent met het native PHP MySQL-stuurprogramma, vindt u migratie naar de procedurele MySQLi-interface veel gemakkelijker. Aan de andere kant, als je eenmaal PDO onder de knie hebt, kun je het gebruiken met elke gewenste database!


Databaseondersteuning

Het belangrijkste voordeel van PDO ten opzichte van MySQLi is de ondersteuning van database-stuurprogramma's. Op het moment van dit schrijven, PDO ondersteunt 12 verschillende stuurprogramma's, in tegenstelling tot MySQLi, die het ondersteunt MySQL alleen.

Gebruik de volgende code om een ​​lijst af te drukken met alle stuurprogramma's die PDO momenteel ondersteunt:

var_dump (BOB :: getAvailableDrivers ());

Wat betekent dit? Welnu, in situaties waarin u van project moet wisselen om een ​​andere database te gebruiken, maakt PDO het proces transparant. Zo alles wat je hoeft te doen is de verbindingsreeks en enkele query's wijzigen - als ze methoden gebruiken die niet worden ondersteund door uw nieuwe database. Met MySQLi moet u dit doen herschrijf elk stuk code - vragen inbegrepen.


Benoemde parameters

Dit is een andere belangrijke functie die PDO heeft; bindende parameters is aanzienlijk eenvoudiger dan het gebruik van de numerieke binding:

$ params = array (': gebruikersnaam' => 'test', ': email' => $ mail, ': last_login' => time () - 3600); $ pdo-> prepare ('SELECT * FROM gebruikers WHERE gebruikersnaam =: gebruikersnaam EN email =: email AND last_login>: last_login'); $ Pdo-> execute ($ params);

... in tegenstelling tot de MySQLi-manier:

$ query = $ mysqli-> prepare ('SELECT * FROM gebruikers WHERE gebruikersnaam =? EN email =? EN last_login>?'); $ query-> bind_param ('sss', 'test', $ mail, time () - 3600); $ Query-> execute ();

De binding van de parameter vraagteken lijkt korter, maar het is lang niet zo flexibel als parameters met een naam, vanwege het feit dat de ontwikkelaar altijd moet houd de parametervolgorde bij; het voelt "hacky" in sommige omstandigheden.

helaas, MySQLi ondersteunt geen genoemde parameters.


Objecttoewijzing

Zowel PDO als MySQLi kunnen resultaten toewijzen aan objecten. Dit is handig als u geen aangepaste database-abstractielaag wilt gebruiken, maar toch ORM-achtig gedrag wilt. Laten we ons voorstellen dat we een Gebruiker class met enkele eigenschappen, die overeenkomen met veldnamen uit een database.

class Gebruiker public $ id; public $ first_name; public $ last_name; public function info () return '#'. $ this-> id. ':'. $ this-> first_name. ". $ this-> last_name;

Zonder objecttoewijzing zouden we de waarde van elk veld moeten invullen (handmatig of via de constructor) voordat we het kunnen gebruiken info () methode correct.

Dit stelt ons in staat om deze eigenschappen vooraf te definiëren voordat het object zelfs maar is geconstrueerd! Bijvoorbeeld:

$ 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, procedurele manier if ($ result = mysqli_query ($ mysqli, $ query)) while ($ user = mysqli_fetch_object ($ result, 'User')) echo $ user-> info (). "\ N ";  // MySQLi, object georiënteerde manier if ($ result = $ mysqli-> query ($ query)) while ($ user = $ result-> fetch_object ('User')) echo $ user-> info () . "\ n"; 

Veiligheid

Beide bibliotheken bieden SQL-injectiebeveiliging, zolang de ontwikkelaar ze gebruikt zoals ze bedoeld zijn (lees: ontsnappen / parameterbinding met voorbereide verklaringen).

Laten we zeggen dat een hacker probeert een aantal schadelijke SQL-code in te voeren via de HTTP-queryparameters (GET) voor 'gebruikersnaam':

$ _GET ['gebruikersnaam'] = "'; DELETE FROM users; / *"

Als we hier niet aan kunnen ontsnappen, wordt het in de zoekopdracht opgenomen "zoals het is" - alle rijen verwijderen uit de gebruikers tabel (zowel PDO en mysqli ondersteunen meerdere query's).

// BOB, "handmatige" escaping $ gebruikersnaam = BOB :: quote ($ _ GET ['gebruikersnaam']); $ pdo-> query ("SELECT * FROM gebruikers WHERE gebruikersnaam = $ gebruikersnaam"); // mysqli, "handmatige" escaping $ gebruikersnaam = mysqli_real_escape_string ($ _ GET ['gebruikersnaam']); $ mysqli-> query ("SELECT * FROM gebruikers WHERE gebruikersnaam = '$ gebruikersnaam'");

Zoals je kunt zien, BOB :: citaat () niet alleen ontsnapt aan de string, maar ook aanhalingstekens. Aan de andere kant, mysqli_real_escape_string () zal alleen aan de string ontsnappen; je moet de offertes handmatig toepassen.

// PDO, voorbereide instructie $ pdo-> prepare ('SELECT * FROM gebruikers WHERE gebruikersnaam =: gebruikersnaam'); $ pdo-> execute (array (': gebruikersnaam' => $ _GET ['gebruikersnaam'])); // mysqli, prepared statements $ query = $ mysqli-> prepare ('SELECT * FROM users WHERE username =?'); $ query-> bind_param ('s', $ _GET ['gebruikersnaam']); $ Query-> execute ();

Ik raad aan dat u altijd voorbereide instructies gebruikt met gebonden query's in plaats van PDO :: citaat () en mysqli_real_escape_string ().


Prestatie

Hoewel zowel PDO als MySQLi behoorlijk snel zijn, presteert MySQLi niet veel sneller in benchmarks - ~ 2,5% voor niet-voorbereide uitspraken en ~ 6,5% voor voorbereide uitspraken. Toch is de native MySQL-extensie zelfs sneller dan deze beide. Dus als je echt elk laatste beetje van de prestaties wilt persen, is dat een ding dat je zou kunnen overwegen.


Samenvatting

Uiteindelijk wint PDO deze strijd met gemak. Met ondersteuning voor twaalf verschillende databasedrivers (achttien verschillende databases!) En benoemde parameters, kunnen we het kleine prestatieverlies negeren en wennen aan zijn API. Vanuit veiligheidsoogpunt zijn beide veilig zolang de ontwikkelaar ze gebruikt zoals ze zouden moeten worden gebruikt (lees: voorbereide verklaringen).

Dus als je nog steeds met MySQLi werkt, is het misschien tijd voor verandering!