mysqli ou PDO - quels sont les avantages et les inconvénients? [fermé]


342

À notre place, nous sommes partagés entre l'utilisation de mysqli et PDO pour des choses comme les instructions préparées et le support des transactions. Certains projets utilisent l'un, certains l'autre. Il est peu probable que nous passions à un autre SGBDR.

Je préfère PDO pour la seule raison qu'il autorise les paramètres nommés pour les instructions préparées, et pour autant que je sache, mysqli ne le fait pas.

Y a-t-il d'autres avantages et inconvénients à choisir l'un plutôt que l'autre comme norme alors que nous consolidons nos projets pour utiliser une seule approche?


5
Cet article vous aidera à choisir lequel utiliser. Si vous considérez les performances, cela pourrait vous aider à choisir.
ravi404

3
C'est drôle de voir combien de personnes ont voté positivement et ont mis en vedette une question qui n'est "pas constructive". Le truc, c'est que le fil complet est très constructif - peut-être que les modérateurs devraient en tenir compte pour juger si une question est constructrice ou non?
marlar

@marlar Je suis tellement d'accord avec vous! C'est en effet le plus gros problème sur StackOverflow. D'excellentes questions / discussions sont toujours fermées.
Sliq

Réponses:


243

Eh bien, vous pourriez contester l'aspect orienté objet, les déclarations préparées, le fait que cela devienne une norme, etc. Mais je sais que la plupart du temps, convaincre quelqu'un fonctionne mieux avec une fonction de tueur. Tiens voilà:

Une très bonne chose avec PDO est que vous pouvez récupérer les données, en les injectant automatiquement dans un objet. Si vous ne voulez pas utiliser un ORM (parce que c'est juste un script rapide) mais que vous aimez le mappage d'objets, c'est vraiment cool:

class Student {

    public $id;
    public $first_name;
    public $last_name

    public function getFullName() {
        return $this->first_name.' '.$this->last_name
    }
}

try 
{
    $dbh = new PDO("mysql:host=$hostname;dbname=school", $username, $password)

    $stmt = $dbh->query("SELECT * FROM students");

    /* MAGIC HAPPENS HERE */

    $stmt->setFetchMode(PDO::FETCH_INTO, new Student);


    foreach($stmt as $student)
    {
        echo $student->getFullName().'<br />';
    } 

    $dbh = null;
}
catch(PDOException $e)
{
    echo $e->getMessage();
}

12
y a-t-il une différence entre ce qui précède et $mysqliResult->fetch_object("student");?
Andy Fleming le

2
@ e-satis non, j'utilise PHP. Les champs publics violent l'encapsulation, donc AS A BEST PRACTICEc'est juste ... lol :) Google n'utilise pas les champs publics, seulement les accesseurs: google-styleguide.googlecode.com/svn/trunk/… .
OZ_

6
@ e-satis: Désolé d'avoir sauté, mais des getters et setters sont nécessaires si vous souhaitez contrôler ce qui se passe lorsque les variables sont modifiées. Sinon, vous ne pouvez pas garantir l'état interne de votre objet (c'est particulièrement un problème si vous avez un autre objet à l'intérieur). Ceci est entièrement indépendant de la langue. @OZ_: Détendez-vous. La critique personnelle ne fera que mettre quelqu'un d'autre sur la défensive.
James P.

2
@monadic: D'accord. L'encapsulation est bien sûr un argument valable lorsqu'il s'agit de composants de base, ou d'objets complexes, etc., mais en tant que représentations d'enregistrements qui seraient autrement associés en lecture-écriture. tableaux, cela est acceptable. En outre, il permet une vérification de type plus facile lorsque les enregistrements flottent dans le système.
Dan Lugg

15
@outis J'espère que je ne suis pas en minorité ici, mais je ne pense pas que les réponses devraient être jugées sur leur sécurité envers les nouveaux développeurs. Cela semble dur, mais c'est vrai. Le but d'une réponse sur SO n'est pas seulement de fournir du code copier-coller, mais aussi de fournir une compréhension. Ce n'est pas le travail du répondeur de s'assurer que chaque faille de sécurité ou faille de modèle est couverte dans un exemple, car avouons-le, l'application dans laquelle le code est copié est intrinsèquement différente de toutes les autres applications utilisant le même code.
Mattygabe

57

Le déplacement d'une application d'une base de données à une autre n'est pas très courant, mais tôt ou tard, vous pourriez vous retrouver à travailler sur un autre projet à l'aide d'un SGBDR différent. Si vous êtes à la maison avec PDO, il y aura au moins une chose de moins à apprendre à ce stade.

En dehors de cela, je trouve l'API PDO un peu plus intuitive et elle se sent plus orientée objet. mysqli a l'impression que ce n'est qu'une API procédurale qui a été objectivée, si vous voyez ce que je veux dire. En bref, je trouve que PDO est plus facile à travailler, mais c'est bien sûr subjectif.


25

J'ai commencé à utiliser PDO parce que le support de déclaration est meilleur, à mon avis. J'utilise une couche d'accès aux données ActiveRecord-esque, et il est beaucoup plus facile d'implémenter des instructions générées dynamiquement. La liaison de paramètres de MySQLi doit être effectuée en un seul appel de fonction / méthode, donc si vous ne savez pas jusqu'à l'exécution combien de paramètres vous souhaitez lier, vous êtes obligé d'utiliser call_user_func_array()(je crois que c'est le bon nom de fonction) pour les sélections . Et oubliez la liaison de résultat dynamique simple.

Surtout, j'aime PDO parce que c'est un niveau d'abstraction très raisonnable. Il est facile de l'utiliser dans des systèmes complètement abstraits où vous ne voulez pas écrire SQL, mais il permet également d'utiliser facilement un type de système de requête plus optimisé et pur, ou de mélanger et faire correspondre les deux.


2
La liaison des résultats avec des requêtes générées dynamiquement est possible, nous le faisons dans nos applications. C'est cependant une énorme douleur.
Pim Jager

17

PDO est la norme, c'est ce que la plupart des développeurs s'attendent à utiliser. mysqli était essentiellement une solution sur mesure à un problème particulier, mais il a tous les problèmes des autres bibliothèques spécifiques au SGBD. AOP est l'endroit où tout le travail acharné et la réflexion intelligente iront.


15

Voici autre chose à garder à l'esprit: Pour l'instant (PHP 5.2), la bibliothèque PDO est boguée . C'est plein de bugs étranges. Par exemple: avant de stocker un PDOStatementdans une variable, la variable devrait être unset()d'éviter une tonne de bugs. La plupart d'entre eux ont été corrigés en PHP 5.3 et ils seront publiés début 2009 en PHP 5.3 qui comportera probablement de nombreux autres bogues. Vous devriez vous concentrer sur l'utilisation de PDO pour PHP 6.1 si vous voulez une version stable et sur l'utilisation de PDO pour PHP 5.3 si vous voulez aider la communauté.


2
Je pense que les gains que PDO offre méritent d'être compris et contournés. PHP lui-même est plein de bogues très aggravants, certains que nous ne pouvons même pas contourner efficacement, et pourtant il offre de nombreux avantages qui nous amènent à l'utiliser à la place d'autres options.
Brian Warshaw

11
Uhm, étrange, je n'ai jamais rencontré de bug avec PDO. Et je l'utilise beaucoup.
NikiC

Mysqli a également des bugs. Tous les logiciels ont des bugs.
Bill Karwin

10

Une autre (bonne) différence notable à propos de PDO est que sa PDO::quote()méthode ajoute automatiquement les guillemets inclus, tandis que mysqli::real_escape_string()(et similaires) ne le font pas:

PDO :: quote () place des guillemets autour de la chaîne d'entrée (si nécessaire) et échappe les caractères spéciaux dans la chaîne d'entrée, en utilisant un style de guillemets approprié au pilote sous-jacent.


8

PDO facilitera considérablement la mise à l'échelle si votre site / application Web est vraiment en train de l'être, car vous pouvez configurer quotidiennement des connexions maître et esclave pour répartir la charge sur la base de données, et PHP se dirige vers le passage à PDO en tant que norme.

Info AOP

Mise à l'échelle d'une application Web


6

Dans le sens de la vitesse d'exécution, MySQLi gagne, mais à moins que vous ayez un bon wrapper utilisant MySQLi, ses fonctions traitant des instructions préparées sont horribles.

Il y a encore des bugs dans le mien, mais si quelqu'un le veut, le voici .

Donc en bref, si vous cherchez un gain de vitesse, alors MySQLi; si vous voulez une facilité d'utilisation, alors PDO.


2
en termes de vitesse, pourriez-vous donner des repères?
Julius F

8
Jonathen Robson a fait une comparaison de vitesse décente des deux à jonathanrobson.me/2010/06/mysqli-vs-pdo-benchmarks . Résumé: inserts - presque égal, selects - mysqli est ~ 2,5% plus rapide pour les instructions non préparées / ~ 6,7% plus rapide pour les instructions préparées. Étant donné la petite taille des pénalités de performances, les fonctionnalités et la flexibilité d'utilisation l' PDOemportent généralement sur les performances atteintes.
Adam

1
@Adam Merci d'avoir créé un lien vers mon blog!
jnrbsn

@ daemonfire300 C'est vrai, il n'y a pas besoin de benchmarks. PDO encapsule la bibliothèque mysqli. Je frapperais probablement le ventilateur si quelqu'un pouvait prouver que PDO est plus rapide que mysqli. :-D
Dyin

@jnrbsn êtes-vous d'accord avec Adam sur ce qu'il a dit?
Basit

5

Personnellement, j'utilise PDO, mais je pense que c'est principalement une question de préférence.

PDO a quelques fonctionnalités qui aident contre l'injection SQL ( instructions préparées ), mais si vous faites attention à votre SQL, vous pouvez aussi y parvenir avec mysqli.

Passer à une autre base de données n'est pas tant une raison d'utiliser PDO. Tant que vous n'utilisez pas de "fonctionnalités SQL spéciales", vous pouvez passer d'une base de données à une autre. Cependant, dès que vous utilisez par exemple "SELECT ... LIMIT 1", vous ne pouvez pas accéder à MS-SQL où il s'agit de "SELECT TOP 1 ...". C'est donc problématique de toute façon.


22
MySQLi a préparé des déclarations.
Tour

5

Réponse modifiée.

Après avoir acquis une certaine expérience avec ces deux API, je dirais qu'il existe 2 fonctionnalités de niveau de blocage qui rendent mysqli inutilisable avec les instructions préparées en natif.
Ils ont déjà été mentionnés dans 2 excellentes réponses (encore largement sous-estimées):

  1. Liaison de valeurs à un nombre arbitraire d'espaces réservés
  2. Renvoyer des données sous forme de simple tableau

(tous deux également mentionnés dans cette réponse )

Pour une raison quelconque, mysqli a échoué avec les deux.
De nos jours, il a été amélioré pour le second ( get_result ), mais il ne fonctionne que sur les installations mysqlnd, ce qui signifie que vous ne pouvez pas compter sur cette fonction dans vos scripts.

Pourtant, il n'a pas de lien par valeur, même à ce jour.

Donc, il n'y a qu'un seul choix: AOP

Toutes les autres raisons, telles que

  • espaces réservés nommés (ce sucre de syntaxe est largement surévalué)
  • prise en charge de différentes bases de données (personne ne l'a jamais utilisée)
  • aller chercher dans l'objet (juste du sucre de syntaxe inutile)
  • différence de vitesse (il n'y en a pas)

ne sont pas d'une importance significative.

En même temps, ces deux API manquent de fonctionnalités vraiment importantes , comme

  • identificateur d'espace réservé
  • espace réservé pour les types de données complexes pour rendre la liaison dynamique moins pénible
  • code d'application plus court.

Ainsi, pour couvrir les besoins réels , il faut créer sa propre bibliothèque d'abstraction, basée sur l'une de ces API, en mettant en œuvre des espaces réservés analysés manuellement. Dans ce cas, je préférerais mysqli, car il a un niveau d'abstraction moindre.


Enfin quelqu'un qui connaît et ne nie pas les faits de la vie ...
Ihsan

4

Dans mon script de référence , chaque méthode est testée 10000 fois et la différence du temps total pour chaque méthode est imprimée. Vous devriez le faire sur votre propre configuration, je suis sûr que les résultats varieront!

Voici mes résultats:

  • " SELECT NULL" -> PGO()plus rapide de ~ 0,35 seconde
  • " SHOW TABLE STATUS" -> mysqli()plus rapide de ~ 2,3 secondes
  • " SELECT * FROM users" -> mysqli()plus rapide de ~ 33 secondes

Remarque: en utilisant -> fetch_row () pour mysqli, les noms de colonne ne sont pas ajoutés au tableau, je n'ai pas trouvé de moyen de le faire dans PGO. Mais même si j'utilise -> fetch_array (), mysqli est légèrement plus lent mais toujours plus rapide que PGO (sauf SELECT NULL).


17
Qu'est-ce que PGO? Et plus rapide de 33 secondes ?! Je trouve cela très difficile à croire ...
Alix Axel

3

Une chose que PDO a que MySQLi n'aime pas vraiment, c'est la capacité de PDO à renvoyer un résultat en tant qu'objet d'un type de classe spécifié (par exemple $pdo->fetchObject('MyClass')). MySQLi fetch_object()ne retournera qu'un stdClassobjet.


19
En fait, vous pouvez spécifier une classe manuellement: "object mysqli_result :: fetch_object ([string $ class_name [, array $ params]])" ". stdClass n'est utilisé que si vous ne spécifiez rien.
Andrioid

-4

Il y a une chose à garder à l'esprit.

Mysqli ne prend pas en charge la fonction fetch_assoc () qui retournerait les colonnes avec des clés représentant les noms des colonnes. Bien sûr , il est possible d'écrire votre propre fonction de le faire, ce n'est pas encore très long, mais j'avais vraiment mal à l' écrire (pour les non-croyants: s'il semble facile de vous, essayez sur votre temps et n » t triche :))



2
J'implémentais il y a plus longtemps, mais oui, j'ai vérifié le manuel. Cela fonctionne-t-il avec des déclarations préparées? Je doute ...
Mike

2
En fait, il a un support curieusement partiel. Vous pouvez récupérer des tableaux dans des requêtes régulières mais pas dans des requêtes paramétrées: -!
Álvaro González

1
Pourquoi ne pas supprimer une réponse qui est manifestement erronée?
Majid Fouladpour

2
@MajidFouladpour - La réponse n'est évidemment pas fausse . Il manque juste un peu de contexte. Mysqli ne prend pas entièrement en charge la récupération de tableaux associatifs.
Álvaro González
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.