När vi har tillgång till en databas i PHP har vi två val: MySQLi och PDO. Så vad ska du veta innan du väljer en? Skillnaderna, databasstöd, stabilitet och prestationshänsyn kommer att beskrivas i den här artikeln.
Om du ofta arbetar med databaser i PHP kanske du vill kolla in utbudet av användbara skript och appar för både MySQLi och PDO på Envato Market.
PDO-appar på Envato MarketPDO | mysqli | |
Databasstöd | 12 olika drivrutiner | MySQL bara |
API | OOP | OOP + procedur |
Förbindelse | Lätt | Lätt |
Namngivna parametrar | Ja | Nej |
Objektmappning | Ja | Ja |
Förberedda uttalanden (klientsidan) | Ja | Nej |
Prestanda | Snabb | Snabb |
Lagrade procedurer | Ja | Ja |
Det är en cinch att ansluta till en databas med båda dessa:
// PDO $ pdo = ny BOB ("mysql: värd = localhost; dbname = databas", "användarnamn", "lösenord"); // mysqli, procedurväg $ mysqli = mysqli_connect ('localhost', 'användarnamn', 'lösenord', 'databas'); // mysqli, objektorienterat sätt $ mysqli = nytt mysqli ("localhost", "användarnamn", "lösenord", "databas");
Observera att dessa anslutningsobjekt / resurser kommer att anses existera genom resten av denna handledning.
Både PDO och MySQLi erbjuder ett objektorienterat API, men MySQLi erbjuder också ett procedur API - vilket gör det lättare för nykomlingar att förstå. Om du är bekant med den inbyggda PHP MySQL-drivrutinen hittar du migrering till det processuella MySQLi-gränssnittet mycket lättare. Å andra sidan, när du behärskar PDO, kan du använda den med vilken databas du önskar!
Kärnfördelen med PDO över MySQLi finns i databasdrivrutinsstöd. Vid tidpunkten för detta skrivande, PDO stöder 12 olika drivrutiner, motsats till MySQLi, som stöder MySQL bara.
För att skriva ut en lista över alla drivrutiner som PDO för närvarande stöder använder du följande kod:
var_dump (SUB :: getAvailableDrivers ());
Vad betyder det här? Tja, i situationer där du måste byta projekt för att använda en annan databas, gör PDO processen transparent. Så allt du behöver göra Ändra anslutningssträngen och några frågor - om de använder några metoder som inte stöds av din nya databas. Med MySQLi behöver du skriva om varje bit av kod - frågor som ingår.
Detta är en annan viktig egenskap som PDO har; bindande parametrar är betydligt lättare än att använda den numeriska bindningen:
$ params = array (': användarnamn' => 'test', ': email' => $ mail, ': last_login' => tid () - 3600); $ pdo-> förbereda ('VÄLJ * FRÅN användare WHERE användarnamn =: användarnamn OCH email =: email och last_login>: last_login'); $ Pdo-> execute ($ params);
... motsatta MySQLi-sättet:
$ query = $ mysqli-> förbereda ('VÄLJ * FRÅN användare WHERE användarnamn =? OCH email =? OCH last_login>?'); $ query-> bind_param ('sss', 'test', $ mail, time () - 3600); $ Query-> execute ();
Frågeteckenparameterns bindning kan verka kortare, men det är inte så flexibelt som namngivna parametrar, på grund av att utvecklaren alltid måste hålla reda på parametervärdet; det känns "hacky" under vissa omständigheter.
Tyvärr, MySQLi stöder inte namngivna parametrar.
Både PDO och MySQLi kan kartlägga resultat till objekt. Det här är till nytta om du inte vill använda ett anpassat databasabstraktionslager, men vill ändå använda ORM-liknande beteende. Låt oss föreställa oss att vi har en Användare
klass med vissa egenskaper, som matchar fältnamn från en databas.
klassanvändare public $ id; allmänhet $ first_name; offentlig $ last_name; public function info () return '#'. $ this-> id. ':'. $ this-> first_name. ". $ this-> last_name;
Utan objektmappning skulle vi behöva fylla i varje fält värde (antingen manuellt eller genom konstruktören) innan vi kan använda info()
metod korrekt.
Detta gör att vi kan fördefiniera dessa egenskaper innan objektet är till och med konstruerat! Till exempel:
$ query = "VÄLJ ID, förnamn, efternamn FRÅN användare"; // PDO $ result = $ pdo-> query ($ query); $ result-> setFetchMode (PDO :: FETCH_CLASS, 'User'); medan ($ user = $ result-> hämta ()) echo $ user-> info (). "\ n"; // MySQLI, procedurväg om $ result = mysqli_query ($ mysqli, $ query)) while ($ user = mysqli_fetch_object ($ resultat, 'User')) echo $ user-> info (). "; // MySQLi, objektorienterat sätt om ($ result = $ mysqli-> fråga ($ query)) while ($ user = $ result-> fetch_object ('User')) echo $ user-> info . "\ n";
Båda biblioteken ger SQL-injektionsskydd, så länge som utvecklaren använder dem så som de var avsedda (läs: Escape / Parameterbindning med beredda uttalanden).
Låt oss säga att en hacker försöker injicera någon skadlig SQL genom HTTP-frågeparametern (GET) för användarnamnet:
$ _GET ['användarnamn'] = "'; DELETE FROM users; / *"
Om vi misslyckas med att fly från detta kommer det att inkluderas i frågan "som det är" - raderar alla rader från användare
bord (både PDO och mysqli stöder flera frågor).
// PDO, "manual" escaping $ username = PDO :: citat ($ _ GET ['användarnamn']); $ pdo-> fråga ("VÄLJ * FRÅN användare WHERE användarnamn = $ användarnamn"); // mysqli, "manual" escaping $ username = mysqli_real_escape_string ($ _ GET ['användarnamn']); $ mysqli-> fråga ("VÄLJ * FRÅN användare WHERE användarnamn = '$ användarnamn'");
Som du kan se, PDO :: citat ()
inte bara släpper strängen, men citerar det också. På andra sidan, mysqli_real_escape_string ()
kommer bara att undkomma strängen; du måste ange citaten manuellt.
// PDO, förberedt uttalande $ pdo-> förbereda ('VÄLJ * från användare VAR användarnamn =: användarnamn'); $ pdo-> exekvera (array (': användarnamn' => $ _GET ['användarnamn'])); // mysqli, förberedda uttalanden $ query = $ mysqli-> förbereda ('VÄLJ * FRÅN användare WHERE användarnamn =?'); $ query-> bind_param ('s', $ _GET ['användarnamn']); $ Query-> execute ();
Jag rekommenderar att du alltid använder beredda uttalanden med bundna frågor istället för P
DO :: citat ()
ochmysqli_real_escape_string ()
.
Medan både PDO och MySQLi är ganska snabba, utför MySQLi obetydligt snabbare i riktmärken - ~ 2,5% för icke-beredda uttalanden och ~ 6,5% för beredda. Ändå är den inbyggda MySQL-tillägget ännu snabbare än båda dessa. Så om du verkligen behöver klämma på varje sista bit av prestanda, så är det en sak du kan tänka dig.
I slutändan, PDO vinner denna kamp med lätthet. Med stöd för tolv olika databasdrivrutiner (arton olika databaser!) Och namngivna parametrar kan vi ignorera den lilla prestandaförlusten och vänja sig vid dess API. Från en säkerhetssynpunkt är de båda säkra så länge som utvecklaren använder dem så som de ska användas (läs: förberedda uttalanden).
Så om du fortfarande arbetar med MySQLi kanske det är dags för en förändring!