sql >> Base de Datos >  >> RDS >> Access

Por qué debería usar PHPs PDO para el acceso a la base de datos

Muchos programadores de PHP aprendieron a acceder a las bases de datos utilizando las extensiones MySQL o MySQLi. A partir de PHP 5.1, hay una forma mejor. PHP Data Objects (PDO) proporciona métodos para declaraciones preparadas y para trabajar con objetos que lo harán mucho más productivo.

Generadores y Frameworks CRUD

El código de la base de datos es repetitivo, pero es muy importante hacerlo bien. Ahí es donde entran en juego los marcos y generadores PHP CRUD:le ahorran tiempo al generar automáticamente todo este código repetitivo para que pueda concentrarse en otras partes de la aplicación.

En CodeCanyon, encontrará marcos y generadores CRUD que lo ayudarán a entregar productos de excelente calidad a tiempo. (CRUD es un acrónimo de crear, leer, actualizar y eliminar, las manipulaciones básicas para una base de datos).

  • PHP9 Útiles generadores y marcos PHP CRUD disponibles en CodeCanyonFranc Lucas
  • PHPCree rápidamente una interfaz PHP CRUD con la herramienta generadora avanzada de CRUD de PDOSajal Soni

Introducción a la DOP

PDO—PHP Data Objects—son una capa de acceso a la base de datos que proporciona un método uniforme de acceso a múltiples bases de datos.

No tiene en cuenta la sintaxis específica de la base de datos, pero puede permitir que el proceso de cambio de bases de datos y plataformas sea bastante sencillo, simplemente cambiando la cadena de conexión en muchos casos.

Este tutorial no pretende ser un tutorial completo sobre SQL. Está escrito principalmente para personas que actualmente usan mysqlmysqli extensión para ayudarlos a dar el salto al PDO más portátil y potente.

Cuando se trata de operaciones de base de datos en PHP, PDO ofrece muchas ventajas sobre la sintaxis sin formato. Enumeremos rápidamente algunos:

  • capa de abstracción
  • sintaxis orientada a objetos
  • soporte para declaraciones preparadas
  • mejor manejo de excepciones
  • API seguras y reutilizables
  • soporte para todas las bases de datos populares

Soporte de base de datos

La extensión puede admitir cualquier base de datos para la que se haya escrito un controlador PDO. En el momento de escribir este artículo, están disponibles los siguientes controladores de base de datos:

  • PDO_DBLIB (FreeTDS/Microsoft SQL Server/Sybase)
  • PDO_FIREBIRD (Firebird/Interbase 6)
  • PDO_IBM (IBM DB2)
  • PDO_INFORMIX (Servidor dinámico de IBM Informix)
  • PDO_MYSQL (MySQL 3.x/4.x/5.x)
  • PDO_OCI (Interfaz de llamadas de Oracle)
  • PDO_ODBC (ODBC v3 (IBM DB2, unixODBC y win32 ODBC))
  • PDO_PGSQL (PostgreSQL)
  • PDO_SQLITE (SQLite 3 y SQLite 2)
  • PDO_4D (D)

Todos estos controladores no están necesariamente disponibles en su sistema; esta es una forma rápida de averiguar qué controladores tiene:

print_r(PDO::getAvailableDrivers());

Conectando

Diferentes bases de datos pueden tener métodos de conexión ligeramente diferentes. A continuación, puede ver el método para conectarse a algunas de las bases de datos más populares. Notará que los primeros tres son idénticos, aparte del tipo de base de datos, y luego SQLite tiene su propia sintaxis.

try {
  # MS SQL Server and Sybase with PDO_DBLIB
  $DBH = new PDO("mssql:host=$host;dbname=$dbname", $user, $pass);
  $DBH = new PDO("sybase:host=$host;dbname=$dbname", $user, $pass);
 
  # MySQL with PDO_MYSQL
  $DBH = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);
 
  # SQLite Database
  $DBH = new PDO("sqlite:my/database/path/database.db");
}
catch(PDOException $e) {
    echo $e->getMessage();
}

Tome nota del bloque try/catch. Siempre debe envolver sus operaciones de PDO en un intento/captura y usar el mecanismo de excepción; más sobre esto en breve. Por lo general, solo realizará una única conexión:hay varias enumeradas para mostrarle la sintaxis. $DBH significa 'identificador de base de datos' y se usará a lo largo de este tutorial.

Puede cerrar cualquier conexión configurando el identificador en nulo.

# close the connection
$DBH = null;

Puede obtener más información sobre las opciones específicas de la base de datos y/o las cadenas de conexión para otras bases de datos en PHP.net.

Excepciones y DOP

PDO puede usar excepciones para manejar errores, lo que significa que cualquier cosa que haga con PDO debe estar envuelta en un bloque de prueba/captura. Puede forzar a PDO a uno de los tres modos de error configurando el atributo de modo de error en su identificador de base de datos recién creado. Aquí está la sintaxis:

$DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT );
$DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING );
$DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );

Independientemente del modo de error que establezca, un error de conexión siempre producirá una excepción, y la creación de una conexión siempre debe estar contenida en un bloque try/catch.

PDO::ERRMODE_SILENT

Este es el modo de error predeterminado. Si lo deja en este modo, tendrá que comprobar si hay errores de la forma en que probablemente esté acostumbrado si ha utilizado mysqlmysqli extensiones Los otros dos métodos son más adecuados para la programación SECA.

PDO::ERRMODE_WARNING

Este modo emitirá una advertencia de PHP estándar y permitirá que el programa continúe ejecutándose. Es útil para la depuración.

PDO::ERRMODE_EXCEPTION

Este es el modo que desea en la mayoría de las situaciones. Dispara una excepción, lo que le permite manejar errores con gracia y ocultar datos que podrían ayudar a alguien a explotar su sistema. Este es un ejemplo de cómo aprovechar las excepciones:

# connect to the database
try {
  $DBH = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);
  $DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
 
  # UH-OH! Typed DELECT instead of SELECT!
  $DBH->prepare('DELECT name FROM people');
}
catch(PDOException $e) {
    echo "I'm sorry, Dave. I'm afraid I can't do that.";
    file_put_contents('PDOErrors.txt', $e->getMessage(), FILE_APPEND);
}

Hay un error intencional en la declaración de selección; esto causará una excepción. La excepción envía los detalles del error a un archivo de registro y muestra un mensaje amigable (o no tan amigable) al usuario.

Insertar y actualizar

La inserción de nuevos datos (o la actualización de datos existentes) es una de las operaciones de base de datos más comunes. Usando PHP PDO, este es normalmente un proceso de dos pasos. Todo lo que se cubre en esta sección se aplica por igual tanto a la UPDATEINSERT operaciones.

Este es un ejemplo del tipo de inserción más básico:

# STH means "Statement Handle"
$STH = $DBH->prepare("INSERT INTO folks ( first_name ) values ( 'Cathy' )");
$STH->execute();

También puede realizar la misma operación utilizando exec() método, con una llamada menos. En la mayoría de las situaciones, utilizará el método más largo para poder aprovechar las declaraciones preparadas. Incluso si solo lo va a usar una vez, el uso de declaraciones preparadas lo ayudará a protegerse de los ataques de inyección SQL.

Declaraciones preparadas

El uso de sentencias preparadas lo ayudará a protegerse de la inyección SQL.

Una declaración preparada es una declaración SQL precompilada que se puede ejecutar varias veces enviando solo los datos al servidor. Tiene la ventaja adicional de hacer que los datos utilizados en los marcadores de posición estén automáticamente a salvo de los ataques de inyección SQL.

Utiliza una declaración preparada al incluir marcadores de posición en su SQL. Aquí hay tres ejemplos:uno sin marcadores de posición, uno con marcadores de posición sin nombre y otro con marcadores de posición con nombre.

# no placeholders - ripe for SQL Injection!
$STH = $DBH->prepare("INSERT INTO folks (name, addr, city) values ($name, $addr, $city)");
 
# unnamed placeholders
$STH = $DBH->prepare("INSERT INTO folks (name, addr, city) values (?, ?, ?)");
 
# named placeholders
$STH = $DBH->prepare("INSERT INTO folks (name, addr, city) values (:name, :addr, :city)");

Desea evitar el primer método; está aquí para comparar. La elección de usar marcadores de posición con nombre o sin nombre afectará la forma en que configura los datos para esas declaraciones.

Marcadores de posición sin nombre

# assign variables to each place holder, indexed 1-3
$STH->bindParam(1, $name);
$STH->bindParam(2, $addr);
$STH->bindParam(3, $city);
 
# insert one row
$name = "Daniel"
$addr = "1 Wicked Way";
$city = "Arlington Heights";
$STH->execute();
 
# insert another row with different values
$name = "Steve"
$addr = "5 Circle Drive";
$city = "Schaumburg";
$STH->execute();

Hay dos pasos aquí. Primero, asignamos variables a los distintos marcadores de posición (líneas 2 a 4). Luego, asignamos valores a esos marcadores de posición y ejecutamos la instrucción. Para enviar otro conjunto de datos, simplemente cambie los valores de esas variables y ejecute la instrucción nuevamente.

¿Parece esto un poco difícil de manejar para declaraciones con muchos parámetros? Está. Sin embargo, si sus datos se almacenan en una matriz, hay un atajo fácil:

# the data we want to insert
$data = array('Cathy', '9 Dark and Twisty Road', 'Cardiff');
 
$STH = $DBH->prepare("INSERT INTO folks (name, addr, city) values (?, ?, ?)");
$STH->execute($data);

¡Eso es fácil!

Los datos de la matriz se aplican a los marcadores de posición en orden. $data[0] va al primer marcador de posición, $data[1] el segundo, etc. Sin embargo, si los índices de su matriz no están en orden, esto no funcionará correctamente y deberá volver a indexar la matriz.

Marcadores de posición con nombre

Probablemente puedas adivinar la sintaxis, pero aquí hay un ejemplo:

# the first argument is the named placeholder name - notice named
# placeholders always start with a colon.
$STH->bindParam(':name', $name);

También puede usar un atajo aquí, pero funciona con matrices asociativas. He aquí un ejemplo:

# the data we want to insert
$data = array( 'name' => 'Cathy', 'addr' => '9 Dark and Twisty', 'city' => 'Cardiff' );
 
# the shortcut!
$STH = $DBH->prepare("INSERT INTO folks (name, addr, city) value (:name, :addr, :city)");
$STH->execute($data);

Las claves de su matriz no necesitan comenzar con dos puntos, sino que deben coincidir con los marcadores de posición nombrados. Si tiene una matriz de matrices, puede iterar sobre ellas y simplemente llamar a execute con cada conjunto de datos.

Otra buena característica de los marcadores de posición con nombre es la capacidad de insertar objetos directamente en su base de datos, suponiendo que las propiedades coincidan con los campos con nombre. Aquí hay un objeto de ejemplo y cómo realizaría su inserción:

# a simple object
class person {
    public $name;
    public $addr;
    public $city;
 
    function __construct($n,$a,$c) {
        $this->name = $n;
        $this->addr = $a;
        $this->city = $c;
    }
    # etc ...
}
 
$cathy = new person('Cathy','9 Dark and Twisty','Cardiff');
 
# here's the fun part:
$STH = $DBH->prepare("INSERT INTO folks (name, addr, city) value (:name, :addr, :city)");
$STH->execute((array)$cathy);

Convertir el objeto en una matriz en execute significa que las propiedades se tratan como claves de matriz.

Selección de datos

Los datos se obtienen a través de ->fetch() , un método de su identificador de declaración. Antes de llamar a buscar, es mejor decirle a PDO cómo desea que se obtengan los datos. Tiene las siguientes opciones:

  • PDO::FETCH_ASSOC : devuelve una matriz indexada por nombre de columna.
  • PDO::FETCH_BOTH (predeterminado): devuelve una matriz indexada por nombre y número de columna.
  • PDO::FETCH_BOUND : asigna los valores de sus columnas a las variables establecidas con ->bindColumn() método.
  • PDO::FETCH_CLASS : asigna los valores de sus columnas a las propiedades de la clase nombrada. Creará las propiedades si no existen propiedades coincidentes.
  • PDO::FETCH_INTO : actualiza una instancia existente de la clase nombrada.
  • PDO::FETCH_LAZY :combina PDO::FETCH_BOTH /PDO::FETCH_OBJ , creando los nombres de las variables de objeto a medida que se utilizan.
  • PDO::FETCH_NUM : devuelve una matriz indexada por número de columna.
  • PDO::FETCH_OBJ : devuelve un objeto anónimo con nombres de propiedades que corresponden a los nombres de las columnas.

En realidad, hay tres que cubrirán la mayoría de las situaciones: FETCH_ASSOCFETCH_CLASSFETCH_OBJ . Para establecer el método de obtención, se utiliza la siguiente sintaxis:

$STH->setFetchMode(PDO::FETCH_ASSOC);

También puede establecer el tipo de recuperación directamente dentro de ->fetch() llamada al método.

FETCH_ASSOC

Este tipo de recuperación crea una matriz asociativa, indexada por nombre de columna. Esto debería ser bastante familiar para cualquiera que haya usado las extensiones mysql/mysqli. Aquí hay un ejemplo de selección de datos con este método:

# using the shortcut ->query() method here since there are no variable
# values in the select statement.
$STH = $DBH->query('SELECT name, addr, city from folks');
 
# setting the fetch mode
$STH->setFetchMode(PDO::FETCH_ASSOC);
 
while($row = $STH->fetch()) {
    echo $row['name'] . "\n";
    echo $row['addr'] . "\n";
    echo $row['city'] . "\n";
}

El bucle while seguirá recorriendo el conjunto de resultados una fila a la vez hasta que se complete.

FETCH_OBJ

Este tipo de recuperación crea un objeto de clase estándar para cada fila de datos obtenidos. He aquí un ejemplo:

# creating the statement
$STH = $DBH->query('SELECT name, addr, city from folks');
 
# setting the fetch mode
$STH->setFetchMode(PDO::FETCH_OBJ);
 
# showing the results
while($row = $STH->fetch()) {
    echo $row->name . "\n";
    echo $row->addr . "\n";
    echo $row->city . "\n";
}

FETCH_CLASS

Las propiedades de su objeto se establecen ANTES de llamar al constructor. Esto es importante.

Este método de obtención le permite obtener datos directamente en una clase de su elección. Cuando usa FETCH_CLASS , las propiedades de su objeto se establecen BEFORE se llama el constructor. Léalo de nuevo, es importante. Si no existen propiedades que coincidan con los nombres de las columnas, esas propiedades se crearán (como públicas) para usted.

Esto significa que si sus datos necesitan alguna transformación después de salir de la base de datos, su objeto puede hacerlo automáticamente a medida que se crea cada objeto.

Como ejemplo, imagine una situación en la que la dirección debe ocultarse parcialmente para cada registro. Podríamos hacer esto operando en esa propiedad en el constructor. He aquí un ejemplo:

class secret_person {
    public $name;
    public $addr;
    public $city;
    public $other_data;
 
    function __construct($other = '') {
        $this->address = preg_replace('/[a-z]/', 'x', $this->address);
        $this->other_data = $other;
    }
}

A medida que se obtienen datos en esta clase, la dirección tiene todas sus minúsculas a-z letras reemplazadas por la letra x . Ahora, usar la clase y hacer que se produzca esa transformación de datos es completamente transparente:

$STH = $DBH->query('SELECT name, addr, city from folks');
$STH->setFetchMode(PDO::FETCH_CLASS, 'secret_person');
 
while($obj = $STH->fetch()) {
    echo $obj->addr;
}

Si la dirección fuera '5 Rosebud', vería '5 Rxxxxxx' como salida. Por supuesto, puede haber situaciones en las que desee que se llame al constructor antes de que se asignen los datos. PDO también lo tiene cubierto para esto.

$STH->setFetchMode(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, 'secret_person');

Ahora, cuando repite el ejemplo anterior con este modo de obtención (PDO::FETCH_PROPS_LATE ), la dirección no oscurecerse, ya que se llamó al constructor y se asignaron las propiedades.

Finalmente, si realmente lo necesita, puede pasar argumentos al constructor al obtener datos en objetos con PDO:

$STH->setFetchMode(PDO::FETCH_CLASS, 'secret_person', array('stuff'));

Si necesita pasar datos diferentes al constructor para cada objeto, puede configurar el modo de búsqueda dentro de fetch método:

$i = 0;
while($rowObj =  $STH->fetch(PDO::FETCH_CLASS, 'secret_person', array($i))) {
    // do stuff
    $i++
}

Algunos otros métodos útiles

Si bien esto no pretende cubrir todo en PDO (¡es una gran extensión!), Hay algunos métodos más que querrá saber para hacer cosas básicas con PDO.

$DBH->lastInsertId();

El ->lastInsertId() El método siempre se llama en el identificador de la base de datos, no en el identificador de la declaración, y devolverá la identificación incrementada automáticamente de la última fila insertada por esa conexión.

$DBH->exec('DELETE FROM folks WHERE 1');
$DBH->exec("SET time_zone = '-8:00'");

El ->exec() El método se usa para operaciones que no pueden devolver datos que no sean las filas afectadas. Los anteriores son dos ejemplos del uso del método exec.

$safe = $DBH->quote($unsafe);

El ->quote() El método cita cadenas para que sean seguras de usar en las consultas. Esta es su alternativa si no está usando declaraciones preparadas.

$rows_affected = $STH->rowCount();

El ->rowCount() El método devuelve un número entero que indica el número de filas afectadas por una operación. En al menos una versión conocida de PDO, el método no funcionaba con instrucciones de selección. Sin embargo, funciona correctamente en la versión PHP 5.1.6 y superior.

Si tiene este problema y no puede actualizar PHP, puede obtener el número de filas con lo siguiente:

$sql = "SELECT COUNT(*) FROM folks";
if ($STH = $DBH->query($sql)) {
    # check the row count
    if ($STH->fetchColumn() > 0) {
 
    # issue a real select here, because there's data!
    }
    else {
        echo "No rows matched the query.";
    }
}

Generadores PHP CRUD de CodeCanyon

Puede ahorrarse horas buscando un generador PHP CRUD de CodeCanyon y usándolo en sus proyectos. Estas son cinco de las descargas más populares que puede comenzar a usar ahora mismo.

1. Aplicación multipropósito de Laravel:Sximo 6

El constructor Sximo 6 se basa en los marcos más populares que existen. También recibió una nueva actualización para 2021, lo que lo hace lo más fácil de usar y rico en funciones posible. Algunas de esas características incluyen:

  • gestión de tablas de base de datos
  • plantillas de front-end y back-end
  • editor MySQL de módulos
  • compatibilidad con múltiples imágenes y carga de archivos

Pruébelo si está buscando ahorrar tiempo con una plantilla PHP CRUD.

2. PDO Crud:creador de formularios y gestión de bases de datos

Aquí hay otro poderoso generador CRUD PHP. Esta plantilla de código PHP PDO gestiona bien la base de datos. Pero eso no es todo lo que hace. También puede usar PDO CRUD para crear formularios útiles directamente desde las tablas de su base de datos. Es una característica útil que no tienen muchas otras opciones.

3. Cicool:Página, Formulario, Rest API y Generador CRUD

Cicool es otro constructor multipropósito que vale la pena analizar. No solo ofrece un constructor CRUD, sino que también tiene:

  • constructor de páginas
  • creador de formularios
  • creador de API resto

Además de estas funciones, también puede agregar extensiones a Cicool y personalizar fácilmente su tema.

4. Generador PHP CRUD

¿Generador de panel de administración fácil? Cheque. ¿Interfaz fácil de navegar? Cheque. ¿Análisis en profundidad de la base de datos? Otro cheque. Este generador PHP CRUD tiene todo lo que necesita para crear excelentes paneles y almacenar sus datos. Con diferentes funciones de autenticación de usuario y gestión de derechos, vale la pena echarle un vistazo a esta plantilla PHP de PDO.