PDO vs MySQLi Hvilken skal du bruke?

Når vi har tilgang til en database i PHP, har vi to valg: MySQLi og PDO. Så hva skal du vite før du velger en? Forskjellene, databasestøtte, stabilitet og ytelsesproblemer vil bli skissert i denne artikkelen.

Hvis du ofte arbeider med databaser i PHP, vil du kanskje se utvalget av nyttige skript og apper for både MySQLi og PDO på Envato Market.

PDO apps på Envato Market

Sammendrag

PUD MySQLi
Databasestøtte 12 forskjellige drivere Bare MySQL
API OOP OOP + prosedyre
Forbindelse Lett Lett
Navngitte parametere Ja Nei
Objekt kartlegging Ja Ja
Forberedte uttalelser
(klient side)
Ja Nei
Opptreden Rask Rask
Lagrede prosedyrer Ja Ja

Forbindelse

Det er en cinch å koble til en database med begge disse:

// PDO $ pdo = ny BOB ("mysql: host = localhost; dbname = database", "brukernavn", "passord"); // mysqli, prosedyrisk måte $ mysqli = mysqli_connect ('localhost', 'brukernavn', 'passord', 'database'); // mysqli, objektorientert måte $ mysqli = new mysqli ('localhost', 'brukernavn', 'passord', 'database');

Vær oppmerksom på at disse forbindelsesobjektene / ressursene vil bli vurdert å eksistere gjennom resten av denne opplæringen.


API-støtte

Både PDO og MySQLi tilbyr en objektorientert API, men MySQLi tilbyr også en prosessorisk API - noe som gjør det lettere for nykommere å forstå. Hvis du er kjent med den native PHP MySQL-driveren, vil du finne migrering til det prosessoriske MySQLi-grensesnittet mye lettere. På den annen side, når du behersker PDO, kan du bruke den med hvilken som helst database du ønsker!


Databasestøtte

Kjernen fordel av PDO over MySQLi er i sin database driver støtte. På tidspunktet for denne skrivingen, PDO støtter 12 forskjellige drivere, i motsetning til MySQLi, som støtter Bare MySQL.

For å skrive ut en liste over alle driverne som PDO for øyeblikket støtter, bruk følgende kode:

var_dump (PUD :: getAvailableDrivers ());

Hva betyr dette? Vel, i situasjoner når du må bytte prosjektet for å bruke en annen database, gjør PDO prosessen gjennomsiktig. Så alt du trenger å gjøre Endre tilkoblingsstrengen og noen få spørsmål - hvis de bruker noen metoder som ikke støttes av den nye databasen. Med MySQLi må du omskrive hver del av koden - spørringer inkludert.


Navngitte parametere

Dette er en annen viktig funksjon som PDO har; bindende parametere er betydelig enklere enn å bruke den numeriske bindingen:

$ params = array (': username' => 'test', ': email' => $ mail, ': last_login' => tid () - 3600); $ pdo-> forberede ('VELG * fra brukere hvor brukernavn =: brukernavn og e-post =: email og last_login>: last_login'); $ Pdo-> utføre ($ parametere);

... i motsetning til MySQLi-måten:

$ query = $ mysqli-> forberede ('VELG * fra brukere hvor brukernavn =? og e-post =? og last_login>?'); $ query-> bind_param ('sss', 'test', $ mail, time () - 3600); $ Query-> utføre ();

Spørsmålstegnparameterbindingen kan virke kortere, men det er ikke like fleksibel som navngitte parametre, på grunn av at utvikleren alltid må holde oversikt over parameterbestillingen; det føles "hacky" under noen omstendigheter.

dessverre, MySQLi støtter ikke navngitte parametere.


Objektkartlegging

Både PDO og MySQLi kan kartlegge resultater til objekter. Dette kommer til nytte hvis du ikke vil bruke et tilpasset databaseabstraksjonslag, men vil fortsatt ha ORM-lignende oppførsel. La oss forestille oss at vi har en Bruker klasse med noen egenskaper, som matcher feltnavn fra en database.

klassen bruker offentlig $ id; offentlig $ first_name; offentlig $ last_name; offentlig funksjon info () return '#'. $ this-> id. ':'. $ this-> first_name. ". $ this-> last_name;

Uten objekt kartlegging, må vi fylle hvert felt verdi (enten manuelt eller gjennom konstruktøren) før vi kan bruke info () metode riktig.

Dette gjør det mulig for oss å forhåndsdefinere disse egenskapene før objektet er konstruert enda! For eksempel:

$ query = "SELECT id, first_name, last_name FROM users"; // PDO $ result = $ pdo-> spørring ($ spørring); $ result-> setFetchMode (PDO :: FETCH_CLASS, 'User'); mens ($ user = $ result-> hente ()) echo $ user-> info (). "\ n";  // MySQLI, prosedyrisk måte hvis ($ result = mysqli_query ($ mysqli, $ query)) mens ($ user = mysqli_fetch_object ($ result, 'User')) echo $ user-> info (). "\ N ";  // MySQLi, objektorientert måte hvis ($ result = $ mysqli-> spørring ($ spørring)) mens ($ user = $ result-> fetch_object ('User')) echo $ user-> info . "\ n"; 

Sikkerhet

Begge biblioteker gir SQL-injeksjonssikkerhet, så lenge utvikleren bruker dem slik de var ment (les: escaping / parameter binding med forberedte setninger).

La oss si at en hacker prøver å injisere noen ondsinnet SQL gjennom brukernavnet HTTP-spørringsparameter (GET):

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

Hvis vi unnlater å unnslippe dette, vil det bli inkludert i spørringen "som det er" - sletter alle rader fra brukere bord (både PDO og mysqli støtter flere spørsmål).

// PDO, "manuell" escaping $ username = PDO :: sitat ($ _ GET ['brukernavn']); $ pdo-> spørring ("SELECT * FROM users WHERE brukernavn = $ brukernavn"); // mysqli, "manual" escaping $ username = mysqli_real_escape_string ($ _ GET ['brukernavn']); $ mysqli-> spørring ("VELG * FRA brukere WHERE brukernavn = '$ brukernavn'");

Som du kan se, PUD :: quote () ikke bare unngår strengen, men den citerer også den. På den andre siden, mysqli_real_escape_string () vil bare unnslippe strengen; du må bruke anførselstegnene manuelt.

// PDO, utarbeidet uttalelse $ pdo-> klargjør ('VELG * FRA brukere WHERE brukernavn =: brukernavn'); $ pdo-> utfør (array (': brukernavn' => $ _GET ['brukernavn'])); // mysqli, utarbeidede uttalelser $ query = $ mysqli-> forberede ('VELG * fra brukere hvor brukernavn =?'); $ query-> bind_param ('s', $ _GET ['brukernavn']); $ Query-> utføre ();

Jeg anbefaler at du alltid bruker utarbeidede uttalelser med bundet søk i stedet for PDO :: quote () og mysqli_real_escape_string ().


Opptreden

Mens både PDO og MySQLi er ganske raske, utfører MySQLi ubetydelig raskere i referanser - ~ 2,5% for ikke-forberedte setninger, og ~ 6,5% for forberedte. Likevel er den native MySQL-utvidelsen enda raskere enn begge disse. Så hvis du virkelig trenger å presse hver siste bit av ytelse, det er en ting du kanskje bør vurdere.


Sammendrag

Til slutt vinner PDO denne kampen med letthet. Med støtte for tolv forskjellige databasedrivere (atten forskjellige databaser!) Og navngitte parametere, kan vi ignorere det lille ytelsestapet, og bli vant til API-en. Fra et sikkerhetsmessig synspunkt er begge de trygge så lenge utvikleren bruker dem slik de skal brukes (les: utarbeidede uttalelser).

Så hvis du fortsatt jobber med MySQLi, er det kanskje dags for en endring!