mysqli o PDO: ¿cuáles son los pros y los contras? [cerrado]

342

En nuestro lugar, estamos divididos entre el uso de mysqli y PDO para cosas como declaraciones preparadas y soporte de transacciones. Algunos proyectos usan uno, otro el otro. Hay pocas posibilidades realistas de que alguna vez nos traslademos a otro RDBMS.

Prefiero PDO por la única razón de que permite parámetros con nombre para declaraciones preparadas, y que yo sepa, mysqli no lo hace.

¿Hay otros pros y contras para elegir uno sobre el otro como estándar a medida que consolidamos nuestros proyectos para usar solo un enfoque?

Polsonby
fuente
55
Este artículo te ayudará a elegir cuál usar. Si considera el rendimiento, esto podría ayudarlo a elegir.
ravi404
3
Es curioso cuántas personas han votado y protagonizado una pregunta que "no es constructiva". La cuestión es que el hilo completo es muy constructivo, ¿tal vez los moderadores deberían tener esto en cuenta al juzgar si una pregunta es constructiva o no?
marlar
@marlar taaaaaaaaaaaaaaaan Este es de hecho el mayor problema en StackOverflow. Excelentes preguntas / discusiones siempre están cerradas.
Sliq

Respuestas:

243

Bueno, podría discutir el aspecto orientado a objetos, las declaraciones preparadas, el hecho de que se convierte en un estándar, etc. Pero sé que la mayoría de las veces, convencer a alguien funciona mejor con una característica asesina. Entonces ahí está:

Una cosa realmente agradable con PDO es que puede recuperar los datos e inyectarlos automáticamente en un objeto. Si no quieres usar un ORM (porque es solo un script rápido) pero te gusta la asignación de objetos, es REALMENTE genial:

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();
}
e-satis
fuente
12
¿Hay alguna diferencia entre lo anterior y $mysqliResult->fetch_object("student");?
Andy Fleming
2
@ e-satis no, yo uso PHP. Los campos públicos violan la encapsulación, por AS A BEST PRACTICElo que es solo ... lol :) Google no usa campos públicos, solo accesores : google-styleguide.googlecode.com/svn/trunk/… .
OZ_
66
@ e-satis: Perdón por entrar, pero los getters y setters son necesarios si deseas controlar lo que sucede cuando se cambian las variables. De lo contrario, simplemente no puede garantizar el estado interno de su objeto (esto es especialmente un problema si tiene otro objeto dentro). Esto es completamente independiente del idioma. @OZ_: Tranquilízate. Las críticas personales solo pondrán a alguien más a la defensiva.
James P.
2
@monadic: De acuerdo. La encapsulación es, por supuesto, un argumento válido cuando se trata de componentes centrales u objetos complejos, etc., sin embargo, como representaciones de registros que de otro modo serían asociados de lectura-escritura. matrices, esto es aceptable. Además, permite una verificación de tipo más fácil a medida que los registros flotan en el sistema.
Dan Lugg
15
@outis Espero no estar en la minoría aquí, pero no creo que las respuestas se deban juzgar por su seguridad hacia los nuevos desarrolladores. Suena duro, pero es verdad. El propósito de una respuesta en SO no es solo proporcionar código de copiar y pegar, sino también proporcionar comprensión. No es tarea del respondedor asegurarse de que cada agujero de seguridad o falla de patrón se cubra en un ejemplo, porque seamos sinceros, la aplicación en la que se copia el código es inherentemente diferente a cualquier otra aplicación que use el mismo código.
Mattygabe
57

Mover una aplicación de una base de datos a otra no es muy común, pero tarde o temprano puede encontrarse trabajando en otro proyecto utilizando un RDBMS diferente. Si estás en casa con PDO, entonces habrá al menos una cosa menos que aprender en ese momento.

Aparte de eso, encuentro que la API PDO es un poco más intuitiva y se siente más orientada a objetos. mysqli siente que es solo una API de procedimiento que ha sido objetivada, si sabes a lo que me refiero. En resumen, creo que es más fácil trabajar con PDO, pero eso es, por supuesto, subjetivo.

Theo
fuente
25

Comencé a usar PDO porque, en mi opinión, el soporte de la declaración es mejor. Estoy usando una capa de acceso a datos ActiveRecord-esque, y es mucho más fácil implementar declaraciones generadas dinámicamente. El enlace de parámetros de MySQLi debe realizarse en una sola llamada a función / método, por lo que si no sabe hasta el tiempo de ejecución cuántos parámetros desea enlazar, se ve obligado a usar call_user_func_array()(creo que ese es el nombre de función correcto) para las selecciones . Y olvídate del simple enlace dinámico de resultados.

Sobre todo, me gusta PDO porque es un nivel de abstracción muy razonable. Es fácil de usar en sistemas completamente abstractos donde no desea escribir SQL, pero también facilita el uso de un sistema de tipo de consulta más optimizado y puro, o mezclar y combinar los dos.

Brian Warshaw
fuente
2
El enlace de resultados con consultas dinámicas generadas es posible, lo hacemos en nuestras aplicaciones. Sin embargo, es un gran dolor.
Pim Jager
17

PDO es el estándar, es lo que la mayoría de los desarrolladores esperan usar. mysqli fue esencialmente una solución a medida para un problema en particular, pero tiene todos los problemas de las otras bibliotecas específicas de DBMS. PDO es donde irá todo el trabajo duro y el pensamiento inteligente.

Dave Gregory
fuente
15

Aquí hay algo más a tener en cuenta: por ahora (PHP 5.2) la biblioteca PDO tiene errores . Está lleno de bichos extraños. Por ejemplo: antes de almacenar un PDOStatementen una variable, la variable debe ser unset()para evitar una tonelada de errores. La mayoría de estos se han solucionado en PHP 5.3 y se lanzarán a principios de 2009 en PHP 5.3, que probablemente tendrá muchos otros errores. Debería enfocarse en usar PDO para PHP 6.1 si desea una versión estable y usar PDO para PHP 5.3 si desea ayudar a la comunidad.

Tom
fuente
2
Creo que las ganancias que ofrece PDO valen la pena entenderlas y solucionarlas. PHP en sí está lleno de errores muy agravantes, algunos que ni siquiera podemos solucionar de manera eficiente, y sin embargo, ofrece muchos beneficios que nos hacen usarlo en lugar de otras opciones.
Brian Warshaw
11
Uhm, extraño, nunca experimenté ningún error con PDO. Y lo uso mucho.
NikiC
Mysqli también tiene errores. Todo el software tiene errores.
Bill Karwin
10

Otra diferencia notable (buena) sobre PDO es que su PDO::quote()método agrega automáticamente las comillas adjuntas, mientras que mysqli::real_escape_string()(y similares) no:

PDO :: quote () coloca comillas alrededor de la cadena de entrada (si es necesario) y escapa caracteres especiales dentro de la cadena de entrada, utilizando un estilo de comillas apropiado para el controlador subyacente.

Alix Axel
fuente
8

PDO hará que sea mucho más fácil escalar si su sitio / aplicación web realmente funciona, ya que puede configurar diariamente conexiones maestras y esclavas para distribuir la carga en la base de datos, además de que PHP se dirige a pasar a PDO como estándar.

Información de PDO

Escalar una aplicación web

Dfranc3373
fuente
6

En el sentido de la velocidad de ejecución, MySQLi gana, pero a menos que tenga un buen contenedor usando MySQLi, sus funciones relacionadas con las declaraciones preparadas son horribles.

Todavía hay errores en el mío, pero si alguien lo quiere, aquí está .

En resumen, si está buscando una ganancia de velocidad, entonces MySQLi; si quieres facilidad de uso, entonces PDO.

Ry-
fuente
2
en sentido de velocidad, ¿podrías dar puntos de referencia?
Julius F el
8
Jonathen Robson ha hecho una comparación de velocidad decente de los dos en jonathanrobson.me/2010/06/mysqli-vs-pdo-benchmarks . Resumen: inserts - casi igual, selects - mysqli es ~ 2.5% más rápido para declaraciones no preparadas / ~ 6.7% más rápido para declaraciones preparadas. Dado lo pequeñas que son las penalizaciones de rendimiento, las características y la flexibilidad del uso PDOgeneralmente superan el impacto en el rendimiento.
Adam
1
@ Adam ¡Gracias por enlazar a mi blog!
jnrbsn
@ daemonfire300 Esto es cierto, no hay necesidad de puntos de referencia. PDO envuelve la biblioteca mysqli. Probablemente golpearía al ventilador si alguien pudiera probar que PDO es más rápido que mysqli. :-D
Dyin
@jnrbsn ¿estás de acuerdo con Adam en lo que dijo?
Basit
5

Personalmente uso PDO, pero creo que es principalmente una cuestión de preferencia.

PDO tiene algunas características que ayudan contra la inyección SQL ( declaraciones preparadas ), pero si tiene cuidado con su SQL, también puede lograrlo con mysqli.

Mudarse a otra base de datos no es tanto una razón para usar PDO. Siempre que no use "características especiales de SQL", puede cambiar de una base de datos a otra. Sin embargo, tan pronto como utilice, por ejemplo, "SELECCIONE ... LÍMITE 1", no podrá ir a MS-SQL donde está "SELECCIONE EL SUPERIOR 1 ...". Entonces esto es problemático de todos modos.

BlaM
fuente
22
MySQLi ha preparado declaraciones.
Torre
5

Respuesta editada

Después de tener algo de experiencia con ambas API, diría que hay 2 características de nivel de bloqueo que hacen que mysqli sea inutilizable con declaraciones preparadas nativas.
Ya se mencionaron en 2 respuestas excelentes (aunque subestimadas):

  1. Valores de enlace a un número arbitrario de marcadores de posición
  2. Devolver datos como una simple matriz

(ambos también mencionados en esta respuesta )

Por alguna razón, mysqli falló con ambos.
Hoy en día obtuvo algunas mejoras para el segundo ( get_result ), pero solo funciona en instalaciones mysqlnd, lo que significa que no puede confiar en esta función en sus scripts.

Sin embargo, no tiene vinculación por valor, incluso hasta el día de hoy.

Entonces, solo hay una opción: DOP

Todas las otras razones, como

  • marcadores de posición nombrados (este azúcar de sintaxis está sobrevalorado)
  • Soporte de bases de datos diferentes (en realidad nadie lo usó)
  • buscar en el objeto (solo azúcar de sintaxis inútil)
  • diferencia de velocidad (no hay ninguna)

no son de importancia significativa.

Al mismo tiempo, estas dos API carecen de algunas características realmente importantes , como

  • marcador de posición de identificador
  • marcador de posición para los tipos de datos complejos para hacer que el enlace dinámico sea menos engorroso
  • Código de aplicación más corto.

Entonces, para cubrir las necesidades de la vida real , uno tiene que crear su propia biblioteca de abstracción, basada en una de estas API, implementando marcadores de posición analizados manualmente. En este caso, preferiría mysqli, ya que tiene un menor nivel de abstracción.

Su sentido común
fuente
Finalmente alguien que sabe y no niega los hechos de la vida ...
Ihsan
4

En mi script de referencia , cada método se prueba 10000 veces y se imprime la diferencia del tiempo total para cada método. Debe hacerlo en su propia configuración, ¡estoy seguro de que los resultados variarán!

Estos son mis resultados:

  • " SELECT NULL" -> PGO()más rápido en ~ 0.35 segundos
  • " SHOW TABLE STATUS" -> mysqli()más rápido en ~ 2.3 segundos
  • " SELECT * FROM users" -> mysqli()más rápido en ~ 33 segundos

Nota: al usar -> fetch_row () para mysqli, los nombres de columna no se agregan a la matriz, no encontré una manera de hacerlo en PGO. Pero incluso si uso -> fetch_array (), mysqli es un poco más lento pero aún más rápido que PGO (excepto SELECT NULL).

Dobb
fuente
17
¿Qué es PGO? ¿Y más rápido por 33 segundos ? Me resulta muy difícil de creer ...
Alix Axel
3

Una cosa que tiene PDO es que MySQLi no es lo que realmente me gusta es la capacidad de PDO de devolver un resultado como un objeto de un tipo de clase específico (por ejemplo $pdo->fetchObject('MyClass')). MySQLi's fetch_object()solo devolverá un stdClassobjeto.

Carne sin etiqueta
fuente
19
En realidad, puede especificar una clase manualmente: "object mysqli_result :: fetch_object ([string $ class_name [, array $ params]])". stdClass solo se usa si no especificas nada.
Andrioid
-4

Hay una cosa a tener en cuenta.

Mysqli no admite la función fetch_assoc () que devolvería las columnas con claves que representan los nombres de las columnas. Por supuesto que es posible escribir su propia función de hacer eso, ni siquiera es muy largo, pero tenía muy cuesta escribirlo (para los no creyentes: si parece fácil para usted, intente por su cuenta algún tiempo y don' t engañar :))

Miguel
fuente
44
¿Probaste el manual? php.net/manual/en/mysqli-result.fetch-assoc.php
Hasta el
2
Se implementó hace más tiempo, pero sí, revisé el manual. ¿Funciona con declaraciones preparadas? Dudo ...
Mike
2
En realidad, tiene un soporte curiosamente parcial. Puede buscar matrices en consultas regulares pero no en consultas parametrizadas: -!
Álvaro González
1
¿Por qué no eliminar una respuesta que obviamente es incorrecta?
Majid Fouladpour
2
@MajidFouladpour: la respuesta no es obviamente incorrecta . Solo le falta algo de contexto. Mysqli no es totalmente compatible con la recuperación de matriz asociativa.
Álvaro González