PDO vs MySQLi Lequel devriez-vous utiliser?

Lorsque vous accédez à une base de données en PHP, nous avons deux choix: MySQLi et PDO. Alors, que devriez-vous savoir avant d'en choisir un? Les différences, le support de base de données, la stabilité et les problèmes de performances seront décrits dans cet article..

Si vous travaillez souvent avec des bases de données en PHP, vous pouvez consulter la gamme de scripts et d'applications utiles pour MySQLi et PDO sur Envato Market..

Applications PDO sur le marché Envato

Résumé

AOP MySQLi
Support de base de données 12 pilotes différents MySQL uniquement
API POO POO + procédural
Lien Facile Facile
Paramètres nommés Oui Non
Mappage d'objets Oui Oui
Déclarations préparées
(côté client)
Oui Non
Performance Vite Vite
Procédures stockées Oui Oui

Lien

C'est très facile de se connecter à une base de données avec ces deux éléments:

// PDO $ pdo = new PDO ("mysql: hôte = localhost; nombase = base de données", "nom d'utilisateur", "mot de passe"); // mysqli, façon procédurale $ mysqli = mysqli_connect ('localhost', 'nom d'utilisateur', 'mot de passe', 'base de données'); // mysqli, manière orientée objet $ mysqli = new mysqli ('localhost', 'nom d'utilisateur', 'mot de passe', 'base de données');

Veuillez noter que ces objets / ressources de connexion seront considérés comme existant dans la suite de ce tutoriel..


Prise en charge des API

PDO et MySQLi offrent tous deux une API orientée objet, mais MySQLi propose également une API procédurale, qui facilite la compréhension des nouveaux arrivants. Si vous connaissez le pilote PHP MySQL natif, la migration vers l'interface procédurale MySQLi sera beaucoup plus facile. D'autre part, une fois que vous maîtrisez le PDO, vous pouvez l'utiliser avec la base de données de votre choix.!


Support de base de données

Le principal avantage de PDO par rapport à MySQLi réside dans son support de pilote de base de données. Au moment d'écrire ces lignes, PDO prend en charge 12 pilotes différents, opposé à MySQLi, qui supporte MySQL uniquement.

Pour imprimer une liste de tous les pilotes actuellement pris en charge par PDO, utilisez le code suivant:

var_dump (PDO :: getAvailableDrivers ());

Qu'est-ce que ça veut dire? Eh bien, dans les situations où vous devez changer de projet pour utiliser une autre base de données, PDO rend le processus transparent. Alors tout ce que vous aurez à faire change la chaîne de connexion et quelques requêtes - si elles utilisent des méthodes non prises en charge par votre nouvelle base de données. Avec MySQLi, vous aurez besoin de réécrire chaque morceau de code - requêtes incluses.


Paramètres nommés

C'est une autre caractéristique importante de PDO. paramètres de liaison est considérablement plus facile que d'utiliser la liaison numérique:

$ params = array (': username' => 'test', ': email' => $ mail, ': last_login' => time () - 3600); $ pdo-> prepare ('SELECT * FROM utilisateurs WHERE nomutilisateur =: nomutilisateur ET email =: email ET last_login>: last_login'); $ pdo-> execute ($ params);

… Opposé à la manière MySQLi:

$ query = $ mysqli-> prepare ('SELECT * DES UTILISATEURS WHERE nomutilisateur =? AND email =? AND last_login>?'); $ query-> bind_param ('sss', 'test', $ mail, time () - 3600); $ query-> execute ();

La liaison du paramètre de point d’interrogation peut sembler plus courte, mais elle est beaucoup moins flexible que les paramètres nommés, car le développeur doit toujours garder une trace de l'ordre des paramètres; il se sent "hacky" dans certaines circonstances.

Malheureusement, MySQLi ne supporte pas les paramètres nommés.


Cartographie d'objets

PDO et MySQLi peuvent mapper les résultats sur des objets. Cela s'avère pratique si vous ne souhaitez pas utiliser une couche d'abstraction de base de données personnalisée, mais souhaitez tout de même un comportement similaire à ORM. Imaginons que nous ayons un Utilisateur classe avec certaines propriétés, qui correspondent aux noms de champs d'une base de données.

utilisateur de classe public $ id; public $ first_name; public $ last_name; fonction publique info () return '#'. $ this-> id. ':'. $ this-> prenom. ". $ this-> last_name;

Sans mappage d’objet, nous aurions besoin de renseigner la valeur de chaque champ (soit manuellement, soit via le constructeur) avant de pouvoir utiliser le paramètre Info() méthode correctement.

Cela nous permet de prédéfinir ces propriétés avant même que l’objet ne soit construit! Par exemple:

$ query = "ID de sélection, prénom, nom de famille FROM utilisateurs"; // PDO $ result = $ pdo-> query ($ query); $ result-> setFetchMode (PDO :: FETCH_CLASS, 'Utilisateur'); while ($ user = $ result-> fetch ()) echo $ user-> info (). "\ n";  // MySQLI, manière procédurale if ($ result = mysqli_query ($ mysqli, $ query)) while ($ user = mysqli_fetch_object ($ result, 'User')) echo $ user-> info (). "\ N ";  // MySQLi, orienté objet if ($ result = $ mysqli-> query ($ query)) while ($ user = $ result-> fetch_object ('User')) echo $ user-> info () . "\ n"; 

Sécurité

Les deux bibliothèques fournissent Sécurité d'injection SQL, tant que le développeur les utilise comme prévu (lire: échappement / liaison de paramètre avec les instructions préparées).

Disons qu'un pirate tente d'injecter du code SQL malveillant via le paramètre de requête HTTP 'nom d'utilisateur' (GET):

$ _GET ['username'] = "'; SUPPRIMER DES UTILISATEURS; / *"

Si nous ne parvenons pas à y échapper, il sera inclus dans la requête "tel quel" - suppression de toutes les lignes de la utilisateurs table (PDO et mysqli supportent plusieurs requêtes).

// PDO, "manual" échappant $ username = PDO :: quote ($ _GET ['username']); $ pdo-> query ("SELECT * FROM utilisateurs WHERE nom_utilisateur = $ nom_utilisateur"); // mysqli, "manual" échappant $ username = mysqli_real_escape_string ($ _GET ['nomutilisateur']); $ mysqli-> query ("SELECT * FROM utilisateurs WHERE nom_utilisateur = '$ nom_utilisateur'");

Comme vous pouvez le voir, AOP :: quote () non seulement échappe à la chaîne, mais cite-la également. D'un autre côté, mysqli_real_escape_string () n'échappera que la chaîne; vous devrez appliquer les guillemets manuellement.

// PDO, instruction préparée $ pdo-> prepare ('SELECT * FROM utilisateurs WHERE nomutilisateur =: nomutilisateur'); $ pdo-> execute (array (': nomutilisateur' => $ _GET ['nomutilisateur'])); // mysqli, instructions préparées $ query = $ mysqli-> prepare ('SELECT * FROM utilisateurs WHERE nom_utilisateur =?'); $ query-> bind_param ('s', $ _GET ['nomutilisateur']); $ query-> execute ();

Je vous recommande de toujours utiliser des instructions préparées avec des requêtes liées au lieu de PDO :: quote () et mysqli_real_escape_string ().


Performance

Bien que PDO et MySQLi soient assez rapides, MySQLi exécute des performances insignifiantes plus rapidement: environ 2,5% pour les instructions non préparées et environ 6,5% pour celles préparées. Malgré tout, l’extension native MySQL est encore plus rapide que les deux. Donc, si vous avez vraiment besoin de tirer le maximum des performances, c’est une chose à considérer..


Résumé

En fin de compte, PDO gagne cette bataille avec facilité. Avec la prise en charge de douze pilotes de base de données différents (dix-huit bases de données différentes!) Et de paramètres nommés, nous pouvons ignorer la petite perte de performances et nous habituer à son API. Du point de vue de la sécurité, les deux sont sécurisés tant que le développeur les utilise comme ils sont censés être utilisés (lire: instructions préparées).

Donc, si vous travaillez toujours avec MySQLi, il est peut-être temps de changer!