Cómo configurar y usar PDO para el acceso a la base de datos en Linux
- 3399
- 111
- Hugo Vera
Objetivo
Aprenda a configurar y usar PDO para el acceso a la base de datos: desde los modos de error hasta obtener métodos.
Requisitos
- Un conocimiento estándar de mysql y
mysql
Cliente de línea de comando; - Estar familiarizado con los conceptos fundamentales de la programación orientada a objetos
- Php> = 5.1
- Tener una base de datos MySQL/mariadb que funcione
Dificultad
MEDIO
Convenciones
- # - requiere que los comandos de Linux dados se ejecuten con privilegios raíz
directamente como usuario raíz o mediante el uso desudo
dominio - ps - Requiere que los comandos de Linux dados se ejecuten como un usuario regular no privilegiado
Introducción
PDO es un acrónimo de Objetos de datos de PHP
: Es una extensión de PHP para interactuar con bases de datos mediante el uso de objetos. Una de sus fortalezas reside en el hecho de que no está estrictamente vinculado a una base de datos particular: su interfaz proporciona una forma común de acceder a varios entornos diferentes, entre los demás:
- Mysql
- Sqlite
- Postgresql
- Microsoft SQL Server
Esta guía tiene como objetivo proporcionar una visión general bastante completa de PDO, guiando al lector paso a paso desde el establecimiento de una conexión a la base de datos, a la elección del modo de recuperación más apropiado, que muestra cómo crear declaraciones preparadas y describiendo los posibles modos de error.
Crear una base de datos y tabla de prueba
Lo primero que vamos a hacer es crear una base de datos para este tutorial:
Crear base de datos Solar_System; Otorgar todos los privilegios en Solar_System.* A 'testUser'@'localhost' identificado por 'testPassword';
Copiar Concedimos al usuario testuser
Todos los privilegios en el sistema solar
base de datos, usando TestPassword
como contraseña. Ahora creemos una tabla y llénela con algunos datos (sin precisión astronómica prevista):
Usar solar_system; Crear planetas de tabla (id Tinyint (1) sin firmar no nulo auto_incement, clave primaria (id), nombre varchar (10) no nulo, color varchar (10) no nulo); Insertar en planetas (nombre, color) valores ('tierra', 'azul'), ('mars', 'rojo'), ('júpiter', 'extraño');
Copiar DSN: Nombre de fuente de datos
Ahora que tenemos una base de datos, debemos definir un Dsn
. DSN significa Nombre de fuente de datos
, y es básicamente un conjunto de información requerida para conectarse a la base de datos, representada en forma de una cadena. La sintaxis puede ser diferente dependiendo de la base de datos a la que desee conectarse, pero como estamos interactuando con MySQL/Mariadb, proporcionaremos:
- El tipo de controlador para usar para la conexión
- El nombre de host de la máquina aloja la base de datos
- El puerto para usar para la conexión (opcional)
- El nombre de la base de datos
- El charset (opcional)
El formato de la cadena, en nuestro caso, sería el siguiente (la vamos a almacenar en el $ DSN
variable):
$ dsn = "mysql: host = localhost; port = 3306; dbname = solar_system; charset = utf8";
Copiar En primer lugar, proporcionamos el prefijo de base de datos
. En este caso, dado que nos estamos conectando a una base de datos MySQL/mariadb, utilizamos mysql
. Luego separamos el prefijo del resto de la cuerda por un colon y cada una de las otras secciones por un punto y coma.
En las siguientes dos secciones especificamos el nombre de host
de la máquina en la que se aloja la base de datos y el puerto
para usar para la conexión. Si no se proporciona este último, se utilizará el predeterminado, que, en este caso, es 3306
. Inmediatamente después de proporcionar el nombre de la base de datos
, y después de eso, el charlatán
usar.
Creando el objeto PDO
Ahora que nuestro DSN está listo, vamos a construir el Objeto PDO
. El constructor PDO toma la cadena DSN como primer parámetro, el nombre del usuario en la base de datos como segundo parámetro, su contraseña como tercera y opcionalmente una matriz de opciones como la cuarta:
$ options = [PDO :: attr_errmode => pdo :: errmode_exception, pdo :: attr_default_fetch_mode => pdo :: fetch_assoc]; $ PDO = nuevo PDO ($ DSN, 'testUser', 'testPassword', $ options);
Copiar Sin embargo, las opciones se pueden especificar también después de que se haya construido el objeto, a través de la SetAttribute ()
método:
$ pdo-> setAttribute (pdo :: att_errmode, pdo :: errmode_exception);
Copiar Establecer el comportamiento de PDO en errores
Echemos un vistazo a algunas de las opciones disponibles para PDO :: ATTR_ERRMODE
. Esta opción es realmente importante, porque define el comportamiento de PDO en caso de errores. Las posibles opciones son:
PDO :: errmode_silent
Este es el valor predeterminado. PDO solo establecerá el código de error y el mensaje de error. Se pueden recuperar usando el código de error()
y ErrorInfo ()
métodos.
PDO :: errmode_exception
Este es, en mi opinión, el recomendado. Con esta opción, además de configurar el código de error y la información, PDO lanzará un PDOException
, que romperá el flujo de script, y es particularmente útil en caso de Transacciones PDO
(Vamos a ver qué transacciones son más tarde en este tutorial).
PDO :: ERRMODE_WARNING
Con esta opción, PDO establecerá el código de error y la información como indexado PDO :: errmode_silent
, pero también emitirá un ADVERTENCIA
, que no romperá el flujo del guión.
Configuración del modo de búsqueda predeterminado
Se puede especificar otra configuración importante a través del PDO :: Default_Fetch_Mode. constante. Le permite especificar el método de búsqueda predeterminado para usar al recuperar los resultados de una consulta. Estas son las opciones más utilizadas:
PDO :: Fetch_Both:
Este es el valor predeterminado. Con él, el resultado recuperado por una consulta de búsqueda será indexado tanto por entero como por nombre de columna. Aplicar este modo de búsqueda al recuperar una fila de la tabla de planetas nos daría este resultado:
$ STMT = $ PDO-> QUERY ("SELECCIONAR * DEL PLANETS"); $ resultados = $ stmt-> fetch (pdo :: fetch_both);
Copiar Array ([id] => 1 [0] => 1 [nombre] => Earth [1] => Earth [Color] => Blue [2] => Blue)
PDO :: Fetch_assoc:
Con esta opción, el resultado se almacenará en un matriz asociativa
en el que cada clave será el nombre de la columna, y cada valor será el valor correspondiente en una fila:
$ STMT = $ PDO-> QUERY ("SELECCIONAR * DEL PLANETS"); $ resultados = $ stmt-> fetch (pdo :: fetch_assoc);
Copiar Array ([id] => 1 [nombre] => Earth [color] => azul)
PDO :: Fetch_num
Este modo de búsqueda devuelve la fila obtenida en un Arriz de 0-indexada:
Array ([0] => 1 [1] => Earth [2] => Blue)
PDO :: fetch_column
Este método de búsqueda es útil al recuperar solo los valores de una columna y devolverá todos los resultados dentro de una matriz simple y unidimensional. Por ejemplo, esta consulta:
$ STMT = $ PDO-> QUERY ("Seleccione el nombre de los planetas");
Copiar Devolvería este resultado:
Array ([0] => Earth [1] => Mars [2] => Júpiter)
PDO :: fetch_key_pair
Este método de búsqueda es útil al recuperar los valores de solo 2 columnas. Devolverá los resultados en forma de una matriz asociativa en la que los valores recuperados de la base de datos para la primera columna especificada en la consulta, se utilizarán como teclas de matriz, mientras que los valores recuperados para la segunda columna representarán la asociativa Valores de matriz:
$ STMT = $ PDO-> QUERY ("Seleccionar nombre, color de los planetas"); $ result = $ stmt-> fetchall (pdo :: fetch_key_pair);
Copiar Volvería:
Array ([Earth] => Blue [Mars] => Red [Jupiter] => Strange)
PDO :: Fetch_Object:
Al usar el PDO :: fetch_object
constante, un objeto anónimo
se creará para cada fila recuperada. Sus propiedades (públicas) llevan el nombre de las columnas, y los resultados de la consulta se utilizarán como sus valores. Aplicar este modo de búsqueda a la misma consulta anterior nos devolvería un resultado en el formulario:
$ resultados = $ stmt-> fetch (pdo :: fetch_obj);
Copiar objeto stdclass ([nombre] => Earth [color] => azul)
PDO :: Fetch_class:
Este modo de búsqueda, como el anterior, asignará el valor de las columnas a las propiedades de un objeto, pero en este caso debemos especificar una clase existente que debe usarse para crear el objeto. Demostremos, primero vamos a crear una clase:
Class Planet private $ name; privado $ color; Función pública setName ($ planet_name) $ this-> name = $ planet_name; función pública setColor ($ planet_color) $ this-> color = $ planet_color; función pública getName () return $ this-> name; función pública getColor () return $ this-> color;
Copiar Ignore la ingenuidad del código anterior y solo observe que las propiedades de la clase del planeta son privado
y la clase no tiene constructor. Ahora intentemos obtener los resultados.
Cuando usas buscar()
con PDO :: fetch_class
debes usar el setFechMode ()
Método en el objeto de instrucción antes de intentar recuperar los datos, por ejemplo:
$ STMT = $ PDO-> QUERY ("Seleccionar nombre, color de los planetas"); $ stmt-> setfetchmode (pdo :: fetch_class, 'planeta');
Copiar Proporcionamos la opción Fetch constante PDO :: fetch_class
Como el primer argumento del método setFetchMode (), y el nombre de la clase que debe usarse para crear el objeto ('planeta' en este caso) como el segundo. Ahora corremos:
$ planet = $ stmt-> fetch ();
Copiar Debería haberse creado un objeto planeta:
var_dump ($ planeta);
Copiar Planet Object ([Nombre: Planeta: Private] => Earth [Color: Planet: Private] => Blue)
Observe cómo los valores recuperados resultantes de la consulta se han asignado a las propiedades correspondientes del objeto incluso si son privados.
Asignación de propiedades después de la construcción de objetos
La clase del planeta no tiene un constructor explícito definido, por lo que no hay problemas al asignar las propiedades; Pero, ¿qué pasaría si la clase tuviera un constructor en el que la propiedad fue asignada o manipulada? Dado que los valores se asignan antes de que se llame al constructor, se habrían sobrescribido.
PDO ayuda a proporcionar el Fetch_props_late
constante: al usarlo, los valores se asignarán a las propiedades después el objeto está construido. Por ejemplo:
Class Planet private $ name; privado $ color; Función pública __construct ($ name = Moon, $ color = Gray) $ this-> name = $ name; $ this-> color = $ color; función pública setName ($ planet_name) $ this-> name = $ planet_name; función pública setColor ($ planet_color) $ this-> color = $ planet_color; función pública getName () return $ this-> name; función pública getColor () return $ this-> color;
Copiar Modificamos nuestra clase de planeta, proporcionando un constructor que toma dos argumentos: el primero es nombre
Y el segundo es color
. Esos argumentos tienen un valor predeterminado respectivamente de luna
y gris
: Esto significa que si no se proporcionan valores explícitamente, esos serán los valores predeterminados asignados.
En este caso, si no usamos Fetch_props_late
, No importa los valores recuperados de la base de datos, las propiedades siempre tendrán los valores predeterminados, porque se sobrescribirán cuando se construya el objeto. Vamos a verificarlo. Primero ejecutamos la consulta:
$ STMT = $ PDO-> QUERY ("Seleccione Nombre, Color de Solar_System Where Name = 'Earth'"); $ stmt-> setfetchmode (pdo :: fetch_class, 'planeta'); $ planet = $ stmt-> fetch ();
Copiar Entonces tiramos el Planeta
objeto y verifique qué valores tienen sus propiedades:
var_dump ($ planeta); Object (planeta)#2 (2) ["nombre": "planeta": privado] => string (4) "luna" ["color": "planeta": private] => string (4) "gris"
Copiar Como se esperaba, los valores recuperados de la base de datos han sido sobrescribidos por los valores predeterminados. Ahora, demostramos cómo este problema se puede resolver utilizando Fetch_props_late
(La consulta es la misma que arriba):
$ stmt-> setFetchMode (pdo :: fetch_class | pdo :: fetch_props_late, 'planet'); $ planet = $ stmt-> fetch (); var_dump ($ planeta); Object (planeta)#4 (2) ["Nombre": "Planeta": privado] => String (5) "Earth" ["Color": "Planet": private] => String (4) "Azul"
Copiar Finalmente obtuvimos los resultados deseados. Pero, ¿qué pasa si el constructor de clase no tiene valores predeterminados y se deben proporcionar? ? Simple: podemos especificar los parámetros del constructor en forma de una matriz como un tercer argumento, después del nombre de clase, en el método setfetchmode (). Por ejemplo, deje cambiar el constructor:
Class Planet private $ name; privado $ color; función pública __construct ($ name, $ color) $ this-> name = $ name; $ this-> color = $ color; […]
Copiar Los argumentos del constructor ahora son obligatorios, por lo que ejecutaríamos:
$ stmt-> setFetchMode (pdo :: fetch_class | pdo :: fetch_props_late, 'planeta', ['luna', 'gris']);
Copiar En este caso, los parámetros que proporcionamos sirven de los valores predeterminados, necesarios para inicializar el objeto sin errores: los valores recuperados de la base de datos los sobrescribirán.
Obtener múltiples objetos
Por supuesto, es posible obtener múltiples resultados como objetos, ya sea usando buscar()
Método dentro de un bucle de tiempo:
while ($ planet = $ stmt-> fetch ()) // Haz cosas con los resultados
Copiar o buscando todos los resultados a la vez. En este caso, como se dijo anteriormente, usando el Fetchall ()
Método, no tiene que especificar el modo de búsqueda antes de llamar al método en sí, pero en el momento en que lo llama:
$ stmt-> fetchall (pdo :: fetch_class | pdo_fetch_props_late, 'planeta', ['luna', 'gris']);
Copiar PDO :: Fetch_into
Con este conjunto de métodos de búsqueda, PDO no creará un nuevo objeto, sino que actualizará las propiedades de uno existente, pero solo si lo son público
, o si usa el __colocar
Método mágico dentro del objeto.
Declaraciones directas preparadas vs
PDO tiene dos formas de ejecutar consultas: una es la forma directa de un paso. El otro, más seguro es usar declaraciones preparadas
.
Consultas directas
Al usar consultas directas, tiene dos métodos principales: consulta()
y exec ()
. El anterior regresa devuelve un PDostatemnt
objeto que puede usar para acceder a los resultados a través del buscar()
o Fetchall ()
Métodos: lo usa para una declaración que no modifica una tabla, como SELECCIONAR
.
Este último, en cambio, devuelve el número de filas que fueron cambiadas por la consulta: la usamos para declaraciones que modifican filas, como INSERTAR
, BORRAR
o ACTUALIZAR
. Las declaraciones directas deben usarse solo cuando no hay variables en la consulta y usted confía absolutamente en que es seguro y se escape adecuadamente.
Declaraciones preparadas
PDO admite también declaraciones preparadas en dos etapas: esto es útil cuando se usa variables en la consulta, y es más seguro en general, porque el preparar()
El método realizará todo el escape necesario para nosotros. Veamos cómo se usan las variables. Imagine que queremos insertar las propiedades de un objeto planeta en el Planetas
mesa. Primero prepararíamos la consulta:
$ stmt = $ pdo-> preparar ("insertar en planetas (nombre, color) valores (?, ?) ");
Copiar Como se dijo antes, primero usaríamos el preparar()
método que toma la consulta SQL como argumento, utilizando marcadores de posición para las variables. Ahora los marcadores de posición pueden ser de dos tipos:
Marcador de posición posicional
Cuando usas ?
marcadores de posición posicionales Podemos obtener un código más conciso, pero debemos proporcionar los valores que se sustituirán en el mismo orden de los nombres de la columna, en una matriz proporcionada como el argumento al ejecutar()
método:
$ stmt-> ejecute ([$ planet-> name, $ planet-> color]);
Copiar Marcadores de posición nombrados
Usando marcadores de posición nombrados
, No tenemos que respetar un pedido en particular, pero vamos a crear un código más detallado. Al ejecutar el ejecutar()
método debemos proporcionar los valores en forma de un matriz asociativa
en el que cada clave sería el nombre del marcador de posición usado, y el valor asociado sería el que se sustituiría en la consulta. Por ejemplo, la consulta anterior se convertiría en:
$ stmt = $ pdo-> preparar ("insertar en planetas (nombre, color) valores (: nombre ,: color)"); $ stmt-> ejecute (['name' => $ planet-> name, 'color' => $ planet-> color]);
Copiar Los métodos de preparación y ejecución se pueden usar tanto al realizar consultas que modifican o simplemente recupera datos de la base de datos. En el primer caso, utilizamos los métodos de búsqueda que vimos anteriormente para recuperar los datos, mientras que en el segundo podemos recuperar el número de filas afectadas utilizando número de filas()
método.
Los métodos BindValue () y BindParam ()
Para proporcionar los valores que se sustituirán en la consulta, también podemos usar el BindValue ()
y BindParam ()
métodos. El primero une el valor de la variable proporcionada al posicional o marcador de posición nombrado con el nombre utilizado al preparar la consulta. Usando el ejemplo anterior, habríamos hecho:
$ stmt-> bindValue ('name', $ planet-> name, pdo :: param_str);
Copiar Vinculamos el valor de $ planet-> nombre
hacia :nombre
marcador de posición. Observe que el uso de los métodos BindValue () y BindParam () podemos especificar, como tercer argumento, el tipo
de la variable, utilizando la constante PDO relacionada, en este caso PDO :: Param_str
.
Usando BindParam ()
, En su lugar, podemos unir la variable al marcador de posición relacionado utilizado al preparar la consulta. Observe que en este caso la variable está sujeto a referencia
, y su valor solo será sustituido al marcador de posición en el momento del ejecutar()
método se llama. La sintaxis es la misma que arriba:
$ stmt-> bindParam ('name', $ planet-> name, pdo :: param_str)
Copiar Limitamos la variable de nombre $ planet-> al :nombre
marcador de posición, no su valor actual! Como se dijo anteriormente, la conversión se realizará justo cuando el ejecutar()
Se llamará al método, por lo que el marcador de posición será sustituido por el valor que la variable tiene en ese momento.
Transacciones PDO
Las transacciones proporcionan una forma de preservar la consistencia al emitir múltiples consultas. Todas las consultas se realizan en un "lote" y se comprometen con la base de datos solo si todas tienen éxito. Las transacciones no funcionarán en todas las bases de datos y no para todos sql
Construcciones, porque algunos de ellos causan y confirman (lista completa aquí)
Con un ejemplo extremo y extraño, imagine que el usuario tiene que seleccionar una lista de planetas, y cada vez que envía una nueva selección, desea eliminar la anterior de la base de datos antes de insertar la nueva. ¿Qué pasaría si la eliminación tiene éxito, pero no la inserción?? Tendríamos un usuario sin planetas! Por lo general, así es como se implementan las transacciones:
$ pdo-> beginTransaction (); intente $ stmt1 = $ pdo-> exec ("eliminar de los planetas"); $ stmt2 = $ pdo-> preparar ("insertar en planetas (nombre, color) valores (?, ?) "); foreach ($ planetas como $ planet) $ stmt2-> ejecute ([$ planet-> getName (), $ planet-> getColor ()]); $ pdo-> commit (); catch ( PdoException $ e) $ pdo-> rollback ();
Copiar En primer lugar el beginTransaction ()
Método del objeto PDO deshabilita la consulta de autocommit, luego dentro de un bloque de captura de try, las consultas se ejecutan en el orden buscado. En este punto si no PDOException
se plantea, las consultas están cometidas con el comprometerse()
método, de lo contrario, a través del Retroceder()
Método, las transacciones se reverten y se restaura en Autocommit.
De esta manera siempre habrá consistencia al emitir múltiples consultas. Es bastante obvio que puedes usar transacciones PDO solo cuando el PDO :: ATTR_ERRMODE
se establece en PDO :: errmode_exception
.
Tutoriales de Linux relacionados:
- Cosas para instalar en Ubuntu 20.04
- Cómo cambiar la contraseña de usuario de mariadb
- Cómo crear una pila de lámparas basada en Docker usando Docker en ..
- Instalación de ampache Raspberry Pi
- Una introducción a la automatización, herramientas y técnicas de Linux
- Instalación de WordPress OpenLitespeed
- Cosas que hacer después de instalar Ubuntu 20.04 fossa focal Linux
- Ubuntu 20.04 WordPress con instalación de Apache
- Ubuntu 20.04: WordPress con instalación de Nginx
- Instale MySQL en Ubuntu 20.04 LTS Linux
- « Cómo instalar Serviio Media Server en Raspberry Pi
- Cómo usar GNU Stow para administrar programas instalados desde Fuente y Dotfiles »