PHP ofrece tres API diferentes para conectarse a MySQL. Estas son mysql(eliminadas a partir de PHP 7) mysqli, y PDOextensiones.
Las mysql_*funciones solían ser muy populares, pero ya no se recomienda su uso. El equipo de documentación está discutiendo la situación de seguridad de la base de datos, y educar a los usuarios para que se alejen de la extensión ext / mysql comúnmente utilizada es parte de esto (ver php.internals: deprecando ext / mysql ).
Y el equipo de desarrolladores de PHP posterior tomó la decisión de generar E_DEPRECATEDerrores cuando los usuarios se conectan a MySQL, ya sea a través de mysql_connect(), mysql_pconnect()o la funcionalidad de conexión implícita incorporada ext/mysql.
ext/mysqlfue oficialmente obsoleto a partir de PHP 5.5 y se ha eliminado a partir de PHP 7 .
¿Ves la caja roja?
Cuando va a cualquier mysql_*página del manual de funciones, ve un cuadro rojo que explica que ya no debe usarse.
Por qué
Alejarse ext/mysqlno solo se trata de seguridad, sino también de tener acceso a todas las funciones de la base de datos MySQL.
ext/mysqlfue construido para MySQL 3.23 y solo obtuvo muy pocas adiciones desde entonces, manteniendo la compatibilidad con esta versión anterior, lo que hace que el código sea un poco más difícil de mantener. Las características faltantes que no son compatibles con ext/mysqlincluyen: ( del manual de PHP ).
Motivo para no usar la mysql_*función :
- No bajo desarrollo activo
- Eliminado a partir de PHP 7
- Carece de una interfaz OO
- No admite consultas asincrónicas sin bloqueo
- No admite declaraciones preparadas o consultas parametrizadas
- No admite procedimientos almacenados
- No soporta múltiples declaraciones
- No admite transacciones
- No es compatible con toda la funcionalidad en MySQL 5.1
Punto anterior citado de la respuesta de Quentin
La falta de soporte para las declaraciones preparadas es particularmente importante ya que proporcionan un método más claro y menos propenso a errores para escapar y citar datos externos que escapar manualmente con una llamada de función separada.
Ver la comparación de extensiones SQL .
Suprimir advertencias de desaprobación
Mientras el código se convierte a MySQLi/ PDO, los E_DEPRECATEDerrores se pueden suprimir configurando error_reportingen php.ini para excluirE_DEPRECATED:
error_reporting = E_ALL ^ E_DEPRECATED
Tenga en cuenta que esto también ocultará otras advertencias de desaprobación , que, sin embargo, pueden ser para otras cosas que no sean MySQL. ( del manual de PHP )
El artículo PDO vs. MySQLi: ¿Cuál debería usar? por Dejan Marjanovic te ayudará a elegir.
Y una mejor manera es PDO, y ahora estoy escribiendo un PDOtutorial simple .
Un tutorial PDO simple y breve
P. La primera pregunta en mi mente fue: ¿qué es 'PDO'?
A. " PDO - PHP Data Objects - es una capa de acceso a la base de datos que proporciona un método uniforme de acceso a múltiples bases de datos".

Conectando a MySQL
Con mysql_*función o podemos decirlo a la antigua usanza (en desuso en PHP 5.5 y superior)
$link = mysql_connect('localhost', 'user', 'pass');
mysql_select_db('testdb', $link);
mysql_set_charset('UTF-8', $link);
Con PDO: Todo lo que necesitas hacer es crear un nuevo PDOobjeto. El constructor acepta parámetros para especificar la fuente de base de datos PDO'constructor s mayormente toma cuatro parámetros que son DSN(nombre de la fuente de datos) y, opcionalmente username, password.
Aquí creo que estás familiarizado con todos excepto DSN; esto es nuevo en PDO. B DSNes básicamente una serie de opciones que indican PDOqué controlador usar y los detalles de conexión. Para mayor referencia, consulte PDO MySQL DSN .
$db = new PDO('mysql:host=localhost;dbname=testdb;charset=utf8', 'username', 'password');
Nota: también puede usar charset=UTF-8, pero a veces causa un error, por lo que es mejor usarlo utf8.
Si hay algún error de conexión, arrojará un PDOExceptionobjeto que puede ser atrapado para manejarlo Exceptionmás.
Buena lectura : Conexiones y gestión de conexiones ¶
También puede pasar varias opciones de controlador como una matriz al cuarto parámetro. Recomiendo pasar el parámetro que pone PDOen modo de excepción. Debido a que algunos PDOcontroladores no admiten declaraciones preparadas nativas, por lo tanto, PDOrealiza la emulación de la preparación. También le permite habilitar manualmente esta emulación. Para usar las declaraciones preparadas nativas del lado del servidor, debe configurarlas explícitamente false.
El otro es desactivar la emulación de preparación que está habilitada en el MySQLcontrolador de forma predeterminada, pero la emulación de preparación debe estar desactivada para usar de PDOmanera segura.
Más adelante explicaré por qué se debe desactivar la emulación de preparación. Para encontrar la razón, consulte esta publicación .
Solo se puede usar si está utilizando una versión anterior MySQLque no recomiendo.
A continuación se muestra un ejemplo de cómo puede hacerlo:
$db = new PDO('mysql:host=localhost;dbname=testdb;charset=UTF-8',
'username',
'password',
array(PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
¿Podemos establecer atributos después de la construcción de PDO?
Sí , también podemos establecer algunos atributos después de la construcción PDO con el setAttributemétodo:
$db = new PDO('mysql:host=localhost;dbname=testdb;charset=UTF-8',
'username',
'password');
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
Manejo de errores
El manejo de errores es mucho más fácil PDOque mysql_*.
Una práctica común cuando se usa mysql_*es:
//Connected to MySQL
$result = mysql_query("SELECT * FROM table", $link) or die(mysql_error($link));
OR die()no es una buena forma de manejar el error, ya que no podemos manejarlo die. Simplemente terminará el script abruptamente y luego hará eco del error en la pantalla que generalmente NO desea mostrar a sus usuarios finales, y permitirá que los hackers sangrientos descubran su esquema. Alternativamente, los valores de retorno de las mysql_*funciones a menudo se pueden usar junto con mysql_error () para manejar errores.
PDOofrece una mejor solución: excepciones. Cualquier cosa que hacemos con PDOdebe ser envuelto en una try- catchbloque. Podemos forzar PDOuno de los tres modos de error configurando el atributo del modo de error. Hay tres modos de manejo de errores a continuación.
PDO::ERRMODE_SILENT. Solo establece códigos de error y actúa casi de la misma manera mysql_*en que debe verificar cada resultado y luego mirar $db->errorInfo();para obtener los detalles del error.
PDO::ERRMODE_WARNINGAumento E_WARNING. (Advertencias en tiempo de ejecución (errores no fatales). La ejecución del script no se detiene).
PDO::ERRMODE_EXCEPTION: Lanzar excepciones. Representa un error provocado por PDO. No debe lanzar un PDOExceptiondesde su propio código. Consulte Excepciones para obtener más información sobre excepciones en PHP. Actúa muy parecido a or die(mysql_error());cuando no es atrapado. Pero a diferencia de esto or die(), PDOExceptionse puede atrapar y manejar con gracia si elige hacerlo.
Buena lectura :
Me gusta:
$stmt->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT );
$stmt->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING );
$stmt->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
Y se puede envolver en try- catch, como a continuación:
try {
//Connect as appropriate as above
$db->query('hi'); //Invalid query!
}
catch (PDOException $ex) {
echo "An Error occured!"; //User friendly message/message you want to show to user
some_logging_function($ex->getMessage());
}
Usted no tiene que manejar con try- catchen este momento. Puede atraparlo en cualquier momento apropiado, pero le recomiendo que use try- catch. También puede tener más sentido detectarlo fuera de la función que llama al PDOmaterial:
function data_fun($db) {
$stmt = $db->query("SELECT * FROM table");
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
//Then later
try {
data_fun($db);
}
catch(PDOException $ex) {
//Here you can handle error and show message/perform action you want.
}
Además, puede manejarlo or die()o podemos decir que me gusta mysql_*, pero será muy variado. Puede ocultar los mensajes de error peligrosos en producción girando display_errors offy simplemente leyendo su registro de errores.
Ahora, después de leer todas las cosas de arriba, es probable que esté pensando: ¿qué diablos es que cuando sólo quiero empezar a inclinarse simples SELECT, INSERT, UPDATE, o DELETEdeclaraciones? No te preocupes, aquí vamos:
Seleccionar datos

Entonces, lo que estás haciendo mysql_*es:
<?php
$result = mysql_query('SELECT * from table') or die(mysql_error());
$num_rows = mysql_num_rows($result);
while($row = mysql_fetch_assoc($result)) {
echo $row['field1'];
}
Ahora adentro PDO, puedes hacer esto como:
<?php
$stmt = $db->query('SELECT * FROM table');
while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
echo $row['field1'];
}
O
<?php
$stmt = $db->query('SELECT * FROM table');
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
//Use $results
Nota : Si está utilizando el método que se muestra a continuación ( query()), este método devuelve un PDOStatementobjeto. Entonces, si desea obtener el resultado, úselo como se indicó anteriormente.
<?php
foreach($db->query('SELECT * FROM table') as $row) {
echo $row['field1'];
}
En PDO Data, se obtiene a través del ->fetch()método de su manejador de estado de cuenta. Antes de llamar a fetch, el mejor enfoque sería decirle a PDO cómo desea que se recuperen los datos. En la sección a continuación estoy explicando esto.
Modos de recuperación
Tenga en cuenta el uso de PDO::FETCH_ASSOCen el código fetch()y fetchAll()arriba. Esto le indica PDOque devuelva las filas como una matriz asociativa con los nombres de campo como claves. También hay muchos otros modos de recuperación que explicaré uno por uno.
En primer lugar, explico cómo seleccionar el modo de búsqueda:
$stmt->fetch(PDO::FETCH_ASSOC)
En lo anterior, he estado usando fetch(). También puedes usar:
Ahora vengo a buscar el modo:
PDO::FETCH_ASSOC: devuelve una matriz indexada por nombre de columna como se devolvió en su conjunto de resultados
PDO::FETCH_BOTH (predeterminado): devuelve una matriz indexada tanto por el nombre de la columna como por el número de la columna indexada en 0 como se devolvió en su conjunto de resultados
¡Incluso hay más opciones! Lea sobre todos ellos en la PDOStatementdocumentación de Fetch. .
Obteniendo el recuento de filas :
En lugar de usar mysql_num_rowspara obtener el número de filas devueltas, puede obtener ay PDOStatementhacer rowCount(), como:
<?php
$stmt = $db->query('SELECT * FROM table');
$row_count = $stmt->rowCount();
echo $row_count.' rows selected';
Obteniendo la última identificación insertada
<?php
$result = $db->exec("INSERT INTO table(firstname, lastname) VAULES('John', 'Doe')");
$insertId = $db->lastInsertId();
Insertar y actualizar o eliminar declaraciones

Lo que estamos haciendo en mysql_*función es:
<?php
$results = mysql_query("UPDATE table SET field='value'") or die(mysql_error());
echo mysql_affected_rows($result);
Y en pdo, esto mismo se puede hacer:
<?php
$affected_rows = $db->exec("UPDATE table SET field='value'");
echo $affected_rows;
En la consulta anterior, PDO::execejecute una instrucción SQL y devuelva el número de filas afectadas.
Insertar y eliminar se cubrirá más adelante.
El método anterior solo es útil cuando no está utilizando variable en la consulta. Pero cuando necesite usar una variable en una consulta, nunca intente como lo anterior y allí para la declaración preparada o la declaración parametrizada .
Declaraciones preparadas
P. ¿Qué es una declaración preparada y por qué los necesito?
R. Una declaración preparada es una declaración SQL precompilada que se puede ejecutar varias veces enviando solo los datos al servidor.
El flujo de trabajo típico de usar una declaración preparada es el siguiente ( citado en Wikipedia tres puntos 3 ):
Preparar : la aplicación crea la plantilla de extracto y la envía al sistema de gestión de bases de datos (DBMS). Ciertos valores se dejan sin especificar, llamados parámetros, marcadores de posición o variables de enlace (etiquetadas a ?continuación):
INSERT INTO PRODUCT (name, price) VALUES (?, ?)
El DBMS analiza, compila y realiza la optimización de consultas en la plantilla de declaración, y almacena el resultado sin ejecutarlo.
- Ejecutar : en un momento posterior, la aplicación proporciona (o enlaza) valores para los parámetros, y el DBMS ejecuta la instrucción (posiblemente devuelve un resultado). La aplicación puede ejecutar la declaración tantas veces como quiera con diferentes valores. En este ejemplo, podría suministrar 'Pan' para el primer parámetro y
1.00para el segundo parámetro.
Puede usar una declaración preparada incluyendo marcadores de posición en su SQL. Básicamente, hay tres sin marcadores de posición (no intente esto con la variable por encima de uno), uno con marcadores de posición sin nombre y uno con marcadores de posición con nombre.
P. Entonces, ¿qué se denominan marcadores de posición y cómo los uso?
A. Marcadores de posición con nombre. Use nombres descriptivos precedidos por dos puntos, en lugar de signos de interrogación. No nos importa la posición / orden de valor en el marcador de posición de nombre:
$stmt->bindParam(':bla', $bla);
bindParam(parameter,variable,data_type,length,driver_options)
También puedes enlazar usando una matriz de ejecución:
<?php
$stmt = $db->prepare("SELECT * FROM table WHERE id=:id AND name=:name");
$stmt->execute(array(':name' => $name, ':id' => $id));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
Otra buena característica para los OOPamigos es que los marcadores de posición con nombre tienen la capacidad de insertar objetos directamente en su base de datos, suponiendo que las propiedades coincidan con los campos con nombre. Por ejemplo:
class person {
public $name;
public $add;
function __construct($a,$b) {
$this->name = $a;
$this->add = $b;
}
}
$demo = new person('john','29 bla district');
$stmt = $db->prepare("INSERT INTO table (name, add) value (:name, :add)");
$stmt->execute((array)$demo);
P. Entonces, ¿qué son marcadores de posición sin nombre y cómo los uso?
A. Tengamos un ejemplo:
<?php
$stmt = $db->prepare("INSERT INTO folks (name, add) values (?, ?)");
$stmt->bindValue(1, $name, PDO::PARAM_STR);
$stmt->bindValue(2, $add, PDO::PARAM_STR);
$stmt->execute();
y
$stmt = $db->prepare("INSERT INTO folks (name, add) values (?, ?)");
$stmt->execute(array('john', '29 bla district'));
En lo anterior, puede ver esos en ?lugar de un nombre como en un marcador de posición de nombre. Ahora, en el primer ejemplo, asignamos variables a los distintos marcadores de posición ( $stmt->bindValue(1, $name, PDO::PARAM_STR);). Luego, asignamos valores a esos marcadores de posición y ejecutamos la declaración. En el segundo ejemplo, el primer elemento de matriz va al primero ?y el segundo al segundo ?.
NOTA : En los marcadores de posición sin nombre , debemos cuidar el orden correcto de los elementos en la matriz que estamos pasando al PDOStatement::execute()método.
SELECT, INSERT, UPDATE, DELETEPreparado consultas
SELECT:
$stmt = $db->prepare("SELECT * FROM table WHERE id=:id AND name=:name");
$stmt->execute(array(':name' => $name, ':id' => $id));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
INSERT:
$stmt = $db->prepare("INSERT INTO table(field1,field2) VALUES(:field1,:field2)");
$stmt->execute(array(':field1' => $field1, ':field2' => $field2));
$affected_rows = $stmt->rowCount();
DELETE:
$stmt = $db->prepare("DELETE FROM table WHERE id=:id");
$stmt->bindValue(':id', $id, PDO::PARAM_STR);
$stmt->execute();
$affected_rows = $stmt->rowCount();
UPDATE:
$stmt = $db->prepare("UPDATE table SET name=? WHERE id=?");
$stmt->execute(array($name, $id));
$affected_rows = $stmt->rowCount();
NOTA:
Sin embargo PDOy / o MySQLino son completamente seguros. Verifique la respuesta ¿Son suficientes las declaraciones preparadas por PDO para evitar la inyección de SQL? por ircmaxell . Además, estoy citando alguna parte de su respuesta:
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$pdo->query('SET NAMES GBK');
$stmt = $pdo->prepare("SELECT * FROM test WHERE name = ? LIMIT 1");
$stmt->execute(array(chr(0xbf) . chr(0x27) . " OR 1=1 /*"));