La extensión MySQLi ( MySQL Improved) es un controlador de base de datos relacional utilizado en el lenguaje de scripting PHP para proporcionar una interfaz con bases de datos compatibles con el protocolo MySQL ( MariaDB , MySQL , Percona Server , TiDB ). [ 1 ] [ 2 ]
MySQLi es una versión mejorada del antiguo controlador PHP MySQL, que ofrece diversas ventajas. [ 3 ] Los autores del lenguaje de scripting PHP recomiendan usar MySQLi al trabajar con versiones de servidor MySQL 4.1.3 y posteriores, ya que aprovecha nuevas funcionalidades. [ 3 ]
Detalles técnicos
El código PHP consta de un núcleo, con extensiones opcionales a la funcionalidad principal. Las extensiones de PHP relacionadas con MySQL, como la extensión MySQLi y la extensión MySQL, se implementan utilizando el marco de extensiones de PHP.
La extensión MySQLi proporciona varias ventajas con respecto a su predecesora, las más destacadas de las cuales (según el sitio web de PHP [ 3 ] ) son:
- Una interfaz orientada a objetos
- Apoyo a las declaraciones preparadas
- Apoyo a múltiples declaraciones
- Soporte para transacciones
- Soporte de depuración mejorado
Comparación de características
Fuente: [ 3 ]
Existen tres opciones principales de API al considerar la conexión a un servidor de base de datos MySQL :
- Extensión MySQLi de PHP
- Objetos de datos PHP (PDO)
- Extensión MySQL de PHP
Uso
Fuente: [ 4 ]
Interfaz dual
La extensión MySQLi cuenta con una interfaz dual: admite tanto el paradigma de programación procedimental como el orientado a objetos.
Los usuarios que migran desde la antigua extensión de MySQL pueden preferir la familiaridad de la interfaz procedimental; en muchos casos, los nombres de las funciones solo se diferencian por el prefijo. Algunas funciones de MySQLi toman un identificador de conexión como primer argumento, mientras que las funciones equivalentes en la antigua interfaz de MySQL lo tomaban como último argumento opcional.
Llamadas a funciones nativas nuevas y antiguas
<?php $mysqli = mysqli_connect ( "example.com" , "user" , "password" , "database" ); $result = mysqli_query ( $mysqli , "SELECT * FROM myDatabase" ); echo mysqli_num_rows ( $result );$mysql = mysql_connect ( "example.com" , "user" , "password" ); mysql_select_db ( "database" ); $result = mysql_query ( "SELECT * FROM myDatabase" , $mysql ); echo mysql_num_rows ( $result ); ?>Conexiones
El servidor MySQL admite el uso de diversas capas de transporte para las conexiones. Las conexiones utilizan TCP/IP, sockets de dominio Unix o tuberías con nombre de Windows.
El nombre de hostlocalhost tiene un significado especial: está vinculado al uso de sockets de dominio Unix. No es posible abrir una conexión TCP/IP usando el nombre de host localhost; en su lugar, 127.0.0.1debe usarse.
Ejemplos de conexión:
<?php $mysqli = new mysqli ( "localhost" , "user" , "password" , "database" ); if ( $mysqli -> connect_errno ) { echo "Error al conectar con MySQL: (" . $mysqli -> connect_errno . ") " . $mysqli -> connect_error ; } echo $mysqli -> host_info . " \n " ;$mysqli = new mysqli ( "127.0.0.1" , "user" , "password" , "database" , 3306 ); if ( $mysqli -> connect_errno ) { echo "Error al conectar con MySQL: (" . $mysqli -> connect_errno . ") " . $mysqli -> connect_error ; }echo $mysqli -> host_info . " \n " ; ?>Producción
Localhost a través de socket UNIX 127.0.0.1 vía TCP/IP
Ejecutando sentencias
Las sentencias pueden ejecutarse con las funciones mysqli_query(), mysqli_real_query() y mysqli_multi_query(). La función mysqli_query() es la más común y combina la sentencia en ejecución con la obtención en búfer de su conjunto de resultados , si los hay, en una sola llamada. Llamar a mysqli_query() es idéntico a llamar a mysqli_real_query() seguido de mysqli_store_result().
Ejemplo:
<?php $mysqli = new mysqli ( "example.com" , "user" , "password" , "database" ); if ( $mysqli -> connect_errno ) { echo "Error al conectar con MySQL: (" . $mysqli -> connect_errno . ") " . $mysqli -> connect_error ; }if ( ! $mysqli -> query ( "DROP TABLE IF EXISTS test" ) || ! $mysqli -> query ( "CREATE TABLE test(id INT)" ) || ! $mysqli -> query ( "INSERT INTO test(id) VALUES (1)" )) { echo "Error al crear la tabla: (" . $mysqli -> errno . ") " . $mysqli -> error ; } ?>Conjuntos de resultados almacenados en búfer
Tras la ejecución de la sentencia, los resultados pueden recuperarse de una sola vez para que el cliente los almacene en búfer o leerse fila por fila. El almacenamiento en búfer del conjunto de resultados del lado del cliente permite al servidor liberar los recursos asociados a los resultados de la sentencia lo antes posible. En general, los clientes consumen los conjuntos de resultados lentamente. Por lo tanto, se recomienda utilizar conjuntos de resultados almacenados en búfer. La función mysqli_query() combina la ejecución de la sentencia y el almacenamiento en búfer del conjunto de resultados.
Las aplicaciones PHP pueden navegar libremente a través de los resultados almacenados en búfer. La navegación es rápida porque los conjuntos de resultados se mantienen en la memoria del cliente.
Ejemplo: Navegación a través de resultados almacenados en búfer
<?php $mysqli = new mysqli ( "example.com" , "user" , "password" , "database" ); if ( $mysqli -> connect_errno ) { echo "Error al conectar con MySQL: (" . $mysqli -> connect_errno . ") " . $mysqli -> connect_error ; }if ( ! $mysqli -> query ( "DROP TABLE IF EXISTS test" ) || ! $mysqli -> query ( "CREATE TABLE test(id INT)" ) || ! $mysqli -> query ( "INSERT INTO test(id) VALUES (1), (2), (3)" )) { echo "Error al crear la tabla: (" . $mysqli -> errno . ") " . $mysqli -> error ; }$res = $mysqli -> query ( "SELECT id FROM test ORDER BY id ASC" );echo "Orden inverso... \n " ; for ( $row_no = $res -> num_rows - 1 ; $row_no >= 0 ; $row_no -- ) { $res -> data_seek ( $row_no ); $row = $res -> fetch_assoc (); echo " id = " . $row [ 'id' ] . " \n " ; }echo "Orden del conjunto de resultados... \n " ; $res -> data_seek ( 0 ); while ( $row = $res -> fetch_assoc ()) { echo " id = " . $row [ 'id' ] . " \n " ; } ?>El ejemplo anterior dará como resultado:
Orden inverso... id = 3 id = 2 id = 1 Orden del conjunto de resultados... id = 1 id = 2 id = 3
Conjuntos de resultados sin búfer
Si la memoria del cliente es un recurso limitado y no es necesario liberar recursos del servidor lo antes posible para mantener baja la carga del servidor, se pueden usar resultados sin búfer. No es posible desplazarse por los resultados sin búfer hasta que se hayan leído todas las filas.
Ejemplo: Navegación a través de resultados sin búfer
<?php $mysqli -> real_query ( "SELECT id FROM test ORDER BY id ASC" ); $res = $mysqli -> use_result ();echo "Orden del conjunto de resultados... \n " ; while ( $row = $res -> fetch_assoc ()) { echo " id = " . $row [ 'id' ] . " \n " ; } ?>Tipos de datos de valores del conjunto de resultados
Las funciones mysqli_query(), mysqli_real_query() y mysqli_multi_query() se utilizan para ejecutar sentencias no preparadas. A nivel del protocolo cliente-servidor de MySQL, se utilizan el comando COM_QUERY y el protocolo de texto para la ejecución de sentencias. Con el protocolo de texto, el servidor MySQL convierte todos los datos de un conjunto de resultados a cadenas antes de enviarlos. Esta conversión se realiza independientemente del tipo de datos de las columnas del conjunto de resultados SQL. Las bibliotecas cliente de MySQL reciben todos los valores de las columnas como cadenas. No se realiza ninguna conversión adicional del lado del cliente para convertir las columnas de nuevo a sus tipos nativos. En su lugar, todos los valores se proporcionan como cadenas PHP.
Ejemplo: El protocolo de texto devuelve cadenas por defecto.
<?php $mysqli = new mysqli ( "example.com" , "user" , "password" , "database" ); if ( $mysqli -> connect_errno ) { echo "Error al conectar con MySQL: (" . $mysqli -> connect_errno . ") " . $mysqli -> connect_error ; }if ( ! $mysqli -> query ( "DROP TABLE IF EXISTS test" ) || ! $mysqli -> query ( "CREATE TABLE test(id INT, label CHAR(1))" ) || ! $mysqli -> query ( "INSERT INTO test(id, label) VALUES (1, 'a')" )) { echo "Error al crear la tabla: (" . $mysqli -> errno . ") " . $mysqli -> error ; }$res = $mysqli -> query ( "SELECT id, label FROM test WHERE id = 1" ); $row = $res -> fetch_assoc ();printf ( "id = %s (%s) \n " , $row [ 'id' ], gettype ( $row [ 'id' ])); printf ( "label = %s (%s) \n " , $row [ 'label' ], gettype ( $row [ 'label' ])); ?>El ejemplo anterior dará como resultado:
id = 1 (cadena) etiqueta = una (cadena)
Es posible convertir columnas enteras y de punto flotante a números PHP configurando la opción de conexión MYSQLI_OPT_INT_AND_FLOAT_NATIVE, si se utiliza la biblioteca mysqlnd. Si se activa, la biblioteca mysqlnd comprobará los tipos de columna de metadatos del conjunto de resultados y convertirá las columnas SQL numéricas a números PHP, si el rango de valores del tipo de datos PHP lo permite. De esta forma, por ejemplo, las columnas SQL INT se devuelven como enteros.
Ejemplo: Tipos de datos nativos con mysqlnd y opción de conexión
<?php $mysqli = mysqli_init (); $mysqli -> options ( MYSQLI_OPT_INT_AND_FLOAT_NATIVE , 1 ); $mysqli -> real_connect ( "example.com" , "user" , "password" , "database" );if ( $mysqli -> connect_errno ) { echo "Error al conectar con MySQL: (" . $mysqli -> connect_errno . ") " . $mysqli -> connect_error ; }if ( ! $mysqli -> query ( "DROP TABLE IF EXISTS test" ) || ! $mysqli -> query ( "CREATE TABLE test(id INT, label CHAR(1))" ) || ! $mysqli -> query ( "INSERT INTO test(id, label) VALUES (1, 'a')" )) { echo "Error al crear la tabla: (" . $mysqli -> errno . ") " . $mysqli -> error ; }$res = $mysqli -> query ( "SELECT id, label FROM test WHERE id = 1" ); $row = $res -> fetch_assoc ();printf ( "id = %s (%s) \n " , $row [ 'id' ], gettype ( $row [ 'id' ])); printf ( "label = %s (%s) \n " , $row [ 'label' ], gettype ( $row [ 'label' ])); ?>El ejemplo anterior dará como resultado:
id = 1 (entero) etiqueta = una (cadena)
Declaraciones preparadas
La base de datos MySQL admite sentencias preparadas. Una sentencia preparada o una sentencia parametrizada se utiliza para ejecutar la misma sentencia repetidamente con alta eficiencia. [ 5 ]
La ejecución de una sentencia preparada consta de dos etapas: preparación y ejecución. En la etapa de preparación, se envía una plantilla de sentencia al servidor de base de datos. El servidor realiza una comprobación de sintaxis e inicializa los recursos internos para su uso posterior.
El servidor MySQL admite el uso de marcadores de posición posicionales anónimos con ?.
Procedimientos almacenados
La base de datos MySQL admite procedimientos almacenados . Un procedimiento almacenado es una subrutina almacenada en el catálogo de la base de datos. Las aplicaciones pueden llamar y ejecutar el procedimiento almacenado. La instrucción SQL CALL se utiliza para ejecutar un procedimiento almacenado. [ 6 ]
Los procedimientos almacenados pueden tener parámetros IN, INOUT y OUT, según la versión de MySQL. La interfaz MySQLi no tiene una noción especial para los diferentes tipos de parámetros.
Los parámetros de entrada se proporcionan con la instrucción CALL. [ 6 ]
Múltiples afirmaciones
MySQL permite opcionalmente tener varias sentencias en una misma cadena. Enviar varias sentencias a la vez reduce los viajes de ida y vuelta entre el cliente y el servidor, pero requiere un manejo especial. [ 7 ]
Se deben ejecutar varias sentencias o consultas con mysqli_multi_query(). Las sentencias individuales de la cadena de sentencias se separan con punto y coma. A continuación, se deben recuperar todos los conjuntos de resultados devueltos por las sentencias ejecutadas.
El servidor MySQL permite tener sentencias que devuelven conjuntos de resultados y sentencias que no devuelven conjuntos de resultados en una misma sentencia múltiple.
Soporte de API para transacciones
El servidor MySQL admite transacciones dependiendo del motor de almacenamiento utilizado. Desde MySQL 5.5, el motor de almacenamiento predeterminado es InnoDB . InnoDB tiene soporte completo para transacciones ACID. [ 8 ]
Las transacciones se pueden controlar mediante SQL o llamadas a la API. Se recomienda usar llamadas a la API para activar y desactivar el modo de confirmación automática, así como para confirmar y revertir transacciones.
Metadatos
Un conjunto de resultados de MySQL contiene metadatos. Estos metadatos describen las columnas que contiene. Todos los metadatos enviados por MySQL son accesibles a través de la interfaz MySQLi. La extensión no realiza cambios, o solo cambios mínimos, en la información que recibe. Las diferencias entre las versiones del servidor MySQL no están alineadas. [ 9 ]
Se accede a los metadatos a través de la interfaz mysqli_result.
La extensión MySQLi y las conexiones persistentes
La compatibilidad con conexiones persistentes se introdujo en PHP 5.3 para la extensión MySQLi. Esta compatibilidad ya estaba presente en PDO MYSQL y ext/mysql. La idea detrás de las conexiones persistentes es que una conexión entre un proceso cliente y una base de datos puede ser reutilizada por un proceso cliente, en lugar de ser creada y destruida varias veces. Esto reduce la sobrecarga de crear nuevas conexiones cada vez que se requiere una, ya que las conexiones no utilizadas se almacenan en caché y están listas para ser reutilizadas. [ 3 ]
A diferencia de la extensión MySQL, MySQLi no proporciona una función independiente para abrir conexiones persistentes. Para abrir una conexión persistente, debe anteponer "p:" al nombre de host al conectarse.
El problema con las conexiones persistentes es que los clientes pueden dejarlas en estados impredecibles. Por ejemplo, se podría activar un bloqueo de tabla antes de que un cliente finalice inesperadamente. Un nuevo proceso cliente que reutilice esta conexión persistente la obtendrá tal cual. El nuevo proceso cliente tendría que realizar cualquier limpieza antes de poder utilizarla correctamente, lo que aumenta la carga de trabajo del programador.
Sin embargo, la conexión persistente de la extensión MySQLi proporciona código de gestión de limpieza integrado. La limpieza realizada por MySQLi incluye:
- Revertir transacciones activas
- Cerrar y desmontar mesas temporales
- Desbloquear tablas
- Restablecer variables de sesión
- Cierre de sentencias preparadas (esto siempre ocurre con PHP)
- manejador cercano
- Libera los bloqueos adquiridos con GET_LOCK().
Esto garantiza que las conexiones persistentes se encuentren en un estado limpio al regresar del grupo de conexiones , antes de que el proceso del cliente las utilice.
La extensión MySQLi realiza esta limpieza llamando automáticamente a la función C-API mysql_change_user().
La función de limpieza automática tiene ventajas y desventajas. La ventaja es que el desarrollador ya no necesita preocuparse por agregar código de limpieza, ya que se ejecuta automáticamente. Sin embargo, la desventaja es que el código podría ser un poco más lento, puesto que debe ejecutarse cada vez que se recibe una conexión del grupo de conexiones.
Es posible desactivar el código de limpieza automática compilando PHP con la variable MYSQLI_NO_CHANGE_USER_ON_PCONNECT definida.
Referencias
- ↑ "PHP: Introducción - Manual" . www.php.net . Consultado el 6 de agosto de 2024 .
- ↑ "Conexión a MySQL/MariaDB/Percona para PHP" . Virtuozzo . Consultado el 22 de noviembre de 2023 .
- 1 2 3 4 5 "Descripción general - Manual" . PHP . Consultado el 11 de agosto de 2014 .
- ↑ "PHP: Guía de inicio rápido - Manual" . In2.php.net . Consultado el 11 de agosto de 2014 .
- ↑ "PHP: Sentencias preparadas - Manual" . In2.php.net . Consultado el 11 de agosto de 2014 .
- 1 2 Jonathon (24 de mayo de 2013). "PHP: Procedimientos almacenados - Manual" . In2.php.net . Recuperado el 11 de agosto de 2014 .
- ↑ eric dot noel at gmail dot com (31 de marzo de 2014). "PHP: Instrucciones múltiples - Manual" . In2.php.net . Consultado el 11 de agosto de 2014 .
- ↑ "PHP: Soporte de API para transacciones - Manual" . In2.php.net . Consultado el 11 de agosto de 2014 .
- ↑ "PHP: Metadatos - Manual" . In2.php.net . Consultado el 11 de agosto de 2014 .
Lecturas adicionales
- Tutorial sobre sentencias preparadas de MySQLi
- Documentación de MySQLi en PHP.net
- Emular la extensión MySQL con MySQLi
- Acceso a datos SQL
- Tecnologías de acceso a datos
- MySQL
- Bibliotecas PHP