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 MarketDOP | MySQLi | |
Soporte de base de datos | 12 conductores diferentes | Solo MySQL |
API | OOP | OOP + procesal |
Conexión | Fácil | Fácil |
Parámetros nombrados | Sí | No |
Mapeo de objetos | Sí | Sí |
Declaraciones preparadas (lado del cliente) | Sí | No |
Actuación | Rápido | Rápido |
Procedimientos almacenados | Sí | Sí |
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.
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!
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.
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.
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";
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 P
DO :: quote ()
ymysqli_real_escape_string ()
.
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.
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.!