DOP vs. MySQLi ¿Qué debería usar?

Al acceder a una base de datos en PHP, tenemos dos opciones: MySQLi y PDO. Entonces, ¿qué debe saber antes de elegir uno? Las diferencias, el soporte de la base de datos, la estabilidad y los problemas de rendimiento se describen en este artículo.

Si trabaja con bases de datos en PHP a menudo, es posible que desee revisar el rango de scripts y aplicaciones útiles para MySQLi y PDO en Envato Market.

Aplicaciones de DOP en Envato Market

Resumen

DOP MySQLi
Soporte de base de datos 12 conductores diferentes Solo MySQL
API OOP OOP + procesal
Conexión Fácil Fácil
Parámetros nombrados No
Mapeo de objetos
Declaraciones preparadas
(lado del cliente)
No
Actuación Rápido Rápido
Procedimientos almacenados

Conexión

Es muy fácil conectarse a una base de datos con estos dos:

// PDO $ pdo = new PDO ("mysql: host = localhost; dbname = database", 'username', 'password'); // mysqli, forma de procedimiento $ mysqli = mysqli_connect ('localhost', 'nombre de usuario', 'contraseña', 'base de datos'); // mysqli, orientado a objetos $ mysqli = new mysqli ('localhost', 'username', 'password', 'database');

Tenga en cuenta que se considerará que estos objetos / recursos de conexión existen a lo largo del resto de este tutorial.


Soporte API

Tanto PDO como MySQLi ofrecen una API orientada a objetos, pero MySQLi también ofrece una API de procedimiento, que facilita la comprensión de los recién llegados. Si está familiarizado con el controlador PHP nativo de MySQL, encontrará que la migración a la interfaz de MySQLi de procedimiento es mucho más fácil. Por otra parte, una vez que domine la DOP, puede usarla con cualquier base de datos que desee!


Soporte de base de datos

La ventaja principal de PDO sobre MySQLi está en su soporte de controlador de base de datos. En el momento de escribir este artículo., DOP soporta 12 controladores diferentes, A diferencia de MySQLi, que soporta Solo MySQL.

Para imprimir una lista de todos los controladores que PDO admite actualmente, use el siguiente código:

var_dump (PDO :: getAvailableDrivers ());

¿Qué significa esto? Bueno, en situaciones en las que tiene que cambiar su proyecto para usar otra base de datos, PDO hace que el proceso sea transparente. Asi que todo lo que tendrás que hacer es cambiar la cadena de conexión y algunas consultas, si utilizan algún método que no sea compatible con su nueva base de datos. Con MySQLi, necesitarás reescribe cada trozo de código - consultas incluidas.


Parámetros con nombre

Esta es otra característica importante que tiene la DOP; parámetros de unión es considerablemente más fácil que utilizar el enlace numérico:

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

... opuesto a la forma MySQLi:

$ query = $ mysqli-> prepare ('SELECT * FROM users WHERE username =? AND email =? AND last_login>?'); $ query-> bind_param ('sss', 'test', $ mail, time () - 3600); $ consulta-> ejecutar ();

El enlace del parámetro de signo de interrogación puede parecer más corto, pero no es tan flexible como los parámetros con nombre, ya que el desarrollador siempre debe realizar un seguimiento del orden de los parámetros; se siente "hacky" en algunas circunstancias.

Desafortunadamente, MySQLi no soporta parámetros nombrados.


Mapeo de objetos

Tanto DOP como MySQLi pueden asignar resultados a objetos. Esto es útil si no desea utilizar una capa de abstracción de base de datos personalizada, pero aún desea un comportamiento similar al ORM. Imaginemos que tenemos un Usuario clase con algunas propiedades, que coinciden con los nombres de campo de una base de datos.

usuario de la clase public $ id; public $ first_name; public $ last_name; información de la función pública () return '#'. $ this-> id. ':'. $ this-> first_name. ". $ this-> last_name;

Sin la asignación de objetos, tendríamos que rellenar el valor de cada campo (ya sea manualmente o mediante el constructor) antes de poder usar el info () método correctamente.

¡Esto nos permite predefinir estas propiedades antes de que el objeto se construya! Por ejemplo:

$ query = "SELECT id, first_name, last_name DE los usuarios"; // DOP $ resultado = $ pdo-> consulta ($ consulta); $ result-> setFetchMode (PDO :: FETCH_CLASS, 'User'); while ($ user = $ result-> fetch ()) echo $ user-> info (). "\ n";  // MySQLI, procedimiento si ($ resultado = mysqli_query ($ mysqli, $ consulta)) while ($ usuario = mysqli_fetch_object ($ resultado, 'Usuario')) echo $ usuario-> info (). "\ N ";  // MySQLi, orientado a objetos si ($ result = $ mysqli-> query ($ query)) while ($ user = $ result-> fetch_object ('User')) echo $ user-> info () ."\norte"; 

Seguridad

Ambas bibliotecas proporcionan Seguridad de inyección SQL, siempre que el desarrollador los use de la forma en que fueron diseñados. (lea: escape / vinculación de parámetros con declaraciones preparadas).

Digamos que un pirata informático está intentando inyectar algo de SQL malicioso a través del parámetro de consulta HTTP (GET) de "nombre de usuario":

$ _GET ['username'] = "'; BORRAR DE los usuarios; / *"

Si no conseguimos escapar de esto, se incluirá en la consulta "tal cual", eliminando todas las filas de la usuarios tabla (tanto PDO como mysqli admiten consultas múltiples).

// DOP, "manual" escaping $ username = PDO :: quote ($ _ GET ['username']); $ pdo-> query ("SELECT * FROM users WHERE username = $ username"); // mysqli, "manual" escaping $ username = mysqli_real_escape_string ($ _ GET ['username']); $ mysqli-> query ("SELECT * FROM users WHERE username = '$ username'");

Como puedes ver, DOP :: cita () No solo se escapa de la cadena, sino que también la cita.. Por otro lado, mysqli_real_escape_string () solo escapará de la cuerda; necesitarás aplicar las citas manualmente.

// DOP, declaración preparada $ pdo-> prepare ('SELECT * FROM users WHERE username =: username'); $ pdo-> execute (array (': username' => $ _GET ['username'))); // mysqli, declaraciones preparadas $ query = $ mysqli-> prepare ('SELECT * FROM users WHERE username =?'); $ consulta-> bind_param ('s', $ _GET ['username']); $ consulta-> ejecutar ();

Recomiendo que siempre use instrucciones preparadas con consultas encuadernadas en lugar de PDO :: quote () y mysqli_real_escape_string ().


Actuación

Si bien tanto PDO como MySQLi son bastante rápidos, MySQLi se desempeña de manera insignificantemente más rápida en los puntos de referencia: ~ 2.5% para declaraciones no preparadas y ~ 6.5% para las preparadas. Aún así, la extensión nativa de MySQL es incluso más rápida que ambas. Entonces, si realmente necesita exprimir hasta el último bit del rendimiento, eso es algo que podría considerar.


Resumen

En última instancia, DOP gana esta batalla con facilidad. Con soporte para doce controladores de base de datos diferentes (¡dieciocho bases de datos diferentes!) Y parámetros con nombre, podemos ignorar la pequeña pérdida de rendimiento y acostumbrarnos a su API. Desde un punto de vista de seguridad, ambos están a salvo siempre que el desarrollador los use de la forma en que se supone que deben ser utilizados (lea: declaraciones preparadas).

Entonces, si todavía estás trabajando con MySQLi, tal vez sea hora de un cambio.!