Diferencia entre revisiones de «Usuario:ManuelRomero/php/BasesDatos»
De WikiEducator
< Usuario:ManuelRomero | php
(→=Bases de datos con PDO) |
|||
(19 revisiones intermedias por el mismo usuario no mostrado) | |||
Línea 2: | Línea 2: | ||
− | |||
<!--__NOEDITSECTION__--> | <!--__NOEDITSECTION__--> | ||
Línea 339: | Línea 338: | ||
$fila = $resultado->fetch_array(); | $fila = $resultado->fetch_array(); | ||
} | } | ||
− | $ | + | $resultado->free(); |
$conexion->close(); | $conexion->close(); | ||
} | } | ||
Línea 430: | Línea 429: | ||
*Para trabajar con consultas preparadas, debemos usar la clase '''''mysqli_stmt''''', e inicializarla con el método '''''stmt_init ''''' | *Para trabajar con consultas preparadas, debemos usar la clase '''''mysqli_stmt''''', e inicializarla con el método '''''stmt_init ''''' | ||
<source lang=php> | <source lang=php> | ||
− | $ | + | $conexion = new mysqli('localhost', 'dwes', 'abc123.', 'dwes'); |
//Preparo el objeto $consulta para crear consultas preparadas en él | //Preparo el objeto $consulta para crear consultas preparadas en él | ||
− | $consulta = $ | + | $consulta = $conexion->stmt_init(); |
</source> | </source> | ||
Los pasos para trabajar con consultas preparadas son: | Los pasos para trabajar con consultas preparadas son: | ||
Línea 439: | Línea 438: | ||
#Una vez que ya no se necesita más, se debe ejecutar el método '''''close'''''. | #Una vez que ya no se necesita más, se debe ejecutar el método '''''close'''''. | ||
<source lang=php> | <source lang=php> | ||
− | $consulta = $ | + | $consulta = $conexion->stmt_init(); |
$consulta->prepare('INSERT INTO familia (cod, nombre) VALUES ("TABLET", "Tablet PC")'); | $consulta->prepare('INSERT INTO familia (cod, nombre) VALUES ("TABLET", "Tablet PC")'); | ||
$consulta->execute(); | $consulta->execute(); | ||
$consulta->close(); | $consulta->close(); | ||
− | $ | + | $conexion->close(); |
</source> | </source> | ||
Línea 470: | Línea 469: | ||
*En el ejemplo que estamos siguiendo | *En el ejemplo que estamos siguiendo | ||
<source lang=php> | <source lang=php> | ||
− | $consulta = $ | + | $consulta = $conexion->stmt_init(); |
$consulta->prepare('INSERT INTO familia (cod, nombre) VALUES (?, ?)'); | $consulta->prepare('INSERT INTO familia (cod, nombre) VALUES (?, ?)'); | ||
$cod_producto = "TABLET"; | $cod_producto = "TABLET"; | ||
Línea 497: | Línea 496: | ||
*Para recorre el conjunto de valores, usamos el método fectch(), como se ve en el ejemplo | *Para recorre el conjunto de valores, usamos el método fectch(), como se ve en el ejemplo | ||
<source lang=php> | <source lang=php> | ||
− | $consulta = $ | + | $consulta = $conexion->stmt_init(); |
$consulta->prepare('SELECT producto, unidades FROM stock WHERE unidades<2'); | $consulta->prepare('SELECT producto, unidades FROM stock WHERE unidades<2'); | ||
$consulta->execute(); | $consulta->execute(); | ||
Línea 505: | Línea 504: | ||
} | } | ||
$consulta->close(); | $consulta->close(); | ||
− | $ | + | $conexion->close(); |
</source> | </source> | ||
*Aquí hay un enlace para una información completa sobre consultas preparadas | *Aquí hay un enlace para una información completa sobre consultas preparadas | ||
Línea 595: | Línea 594: | ||
*En este caso la sentencia se ejecuta envíandola con el métido '''''exec($sentencia)''''' | *En este caso la sentencia se ejecuta envíandola con el métido '''''exec($sentencia)''''' | ||
*Este método retorna un entero que indica en número de registros afectados | *Este método retorna un entero que indica en número de registros afectados | ||
+ | <source lang=sql> | ||
+ | $conexion= new PDO("mysql:host=localhost;db=dwes","root","root"); | ||
+ | $registros = $conexion->exec("DELETE FROM stock WHERE unidades=0"); | ||
+ | print "<p>Se han borrado $registros registros.</p>"; | ||
+ | </source> | ||
+ | ;SELECT | ||
+ | *En este caso debemos usar el método de la clase PDO llamado '''''query($consulta)''''' | ||
+ | *Este método retorna un objeto de la clase '''''PDOStatement''''' http://es1.php.net/manual/es/class.pdostatement.php | ||
+ | *Una vez que tenemos el objeto de la clase ya tenemos ese cursor o conjunto de filas con su puntero | ||
+ | *Para extraer cada fila usamos el método '''''fetch()''''', el cual en caso de que no haya filas que retornar devuelve null (El mismo concepto trabajado hasta ahora). | ||
+ | *Cada vez que hacemos un fetch obtenemos un array con la fila que podemos usar tanto de forma asociativa como indexada. | ||
+ | *Este comportamiento por defecto se puede cambiar, es decir que podemos obligar a que el array que devuelve sea indexado, asociativo o que sea un objeto. | ||
+ | *Para ello debemos pasar al método fetch un valor que lo especifique según la lista siguiente. | ||
+ | *Para cerrar el cursor se emplea el método '''''closeCursor()'''''; muchos gestores de bases de datos necesitas que se libere, antes de ser usado para realizar otra consulta. | ||
+ | #PDO::FETCH_ASSOC. Devuelve solo un array asociativo. | ||
+ | #PDO::FETCH_NUM. Devuelve solo un array con claves numéricas. | ||
+ | #PDO::FETCH_BOTH. Devuelve un array con claves numéricas y asociativas. Es el comportamiento por defecto. | ||
+ | #PDO::FETCH_OBJ. Devuelve un objeto cuyas propiedades se corresponden con los campos del registro. | ||
+ | *A continuación diferentes formas de hacer exactamente lo mismo | ||
+ | <source lang=php> | ||
+ | $conexion = new PDO("mysql:host=localhost;dbname=dwes", "dwes", "abc123."); | ||
+ | $resultado = $dwes->query("SELECT producto, unidades FROM stock"); | ||
+ | while ($registro = $resultado->fetch()) { | ||
+ | echo "Producto ".$registro['producto'].": ".$registro['unidades']."<br />"; | ||
+ | } | ||
+ | </source> | ||
+ | <source lang=php> | ||
+ | $conexion = new PDO("mysql:host=localhost;dbname=dwes", "dwes", "abc123."); | ||
+ | $resultado = $dwes->query("SELECT producto, unidades FROM stock"); | ||
+ | while ($registro = $resultado->fetch(FETCH_ASSOC)) { | ||
+ | echo "Producto ".$registro['producto'].": ".$registro['unidades']."<br />"; | ||
+ | } | ||
+ | </source> | ||
+ | <source lang=php> | ||
+ | $conexion = new PDO("mysql:host=localhost;dbname=dwes", "dwes", "abc123."); | ||
+ | $resultado = $dwes->query("SELECT producto, unidades FROM stock"); | ||
+ | while ($registro = $resultado->fetch(FETCH_NUM)) { | ||
+ | echo "Producto ".$registro[0].": ".$registro[1]."<br />"; | ||
+ | } | ||
+ | </source> | ||
+ | <source lang=php> | ||
+ | $conexion = new PDO("mysql:host=localhost;dbname=dwes", "dwes", "abc123."); | ||
+ | $resultado = $dwes->query("SELECT producto, unidades FROM stock"); | ||
+ | while ($registro = $resultado->fetch(FETCH_OBJECT)) { | ||
+ | echo "Producto ".$registro.producto.": ".$registro.unidades."<br />"; | ||
+ | } | ||
+ | </source> | ||
+ | {{Resumen| | ||
+ | <source lang=php> | ||
+ | $conexion="mysql:host=localhost;dbname=dwes"; | ||
+ | $user="root"; | ||
+ | $pass="root"; | ||
+ | $opciones=$array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"); | ||
+ | |||
+ | $conexion=new PDO($conexion,$usuario,$pass, $opciones); | ||
+ | $consulta = "Select * from ..."; | ||
+ | $sentencia = "Insert into ....." | ||
+ | $resultado = $conexion->exec($sentencia); | ||
+ | $sentencia->closeCursor(); | ||
+ | echo "Se han insertado $resultado filas"; | ||
+ | $resultado = $conexion->query($sconsulta); | ||
+ | while $resultado->fetch(){ | ||
+ | echo "se la leído el valor $resultado[0], ..."; | ||
+ | } | ||
+ | $conexion=null; //Es la manera de liberar a la memoria de este objeto. | ||
+ | |||
+ | </source> | ||
+ | }} | ||
===Consultas preparadas=== | ===Consultas preparadas=== | ||
+ | *Al igual que en mysqli, podemos preparar las consultas. Esta forma de trabajar es cómoda y mas segura que la habitual, según viemos en apartados anteriores | ||
+ | *Para realizar una consulta parametrizada, hay que seguir unos pasos al igual que en '''''mysqli''''' | ||
+ | ;preparar la consulta '''''prepare(...)''''' | ||
+ | *Para ello se pueden pasar con ? los valores de los parámetros o bien poner un nombre precedido de : | ||
+ | <source lang=php> | ||
+ | $conexion = new PDO("mysql:host=localhost;dbname=dwes", "dwes", "abc123."); | ||
+ | $consulta = $conexion->prepare('INSERT INTO familia (cod, nombre) VALUES (?, ?)'); | ||
+ | </source> | ||
+ | Es igual que hacer | ||
+ | <source lang=php> | ||
+ | $conexion = new PDO("mysql:host=localhost;dbname=dwes", "dwes", "abc123."); | ||
+ | $consulta = $conexion->prepare('INSERT INTO familia (cod, nombre) VALUES (:codigoProducto, :nombreProducto)'); | ||
+ | </source> | ||
+ | ;Asignar valores a la consulta pararmetrizada | ||
+ | *Si se han especificado ? se asigna dando a cada parámetro un valor con el método bindParam(posicion, valor) | ||
+ | <source lang=php> | ||
+ | $cod_producto = "TABLET"; | ||
+ | $nombre_producto = "Tablet PC"; | ||
+ | $consulta->bindParam(1, $cod_producto); | ||
+ | $consulta->bindParam(2, $nombre_producto); | ||
+ | </source> | ||
+ | *Si se han especificado con nombre se usan los nombre en lugar de los números | ||
+ | |||
+ | <source lang=php> | ||
+ | $cod_producto = "TABLET"; | ||
+ | $nombre_producto = "Tablet PC"; | ||
+ | $consulta->bindParam(":cod", $cod_producto); | ||
+ | $consulta->bindParam(":nombre", $nombre_producto); | ||
+ | </source> | ||
+ | *Se ejecuta con el método execute() | ||
+ | *Este método permite alternativamente suplir las asignaciones anteriores realizadas con el método bindParam, pasándole en un argumento meditante una array dicha asignación. | ||
+ | *El array utilizado será asociativo o con claves numéricas dependiendo de la forma en que hayas indicado los parámetros. | ||
+ | *En el primer caso | ||
+ | <source lang=php> | ||
+ | $parametros = array["TABLET", ":nombre"]; | ||
+ | $consulta->execute($parametros); | ||
+ | </source> | ||
+ | *En el segundo caso | ||
+ | <source lang=php> | ||
+ | $parametros = array(":cod" => "TABLET", ":nombre" => "Tablet PC"); | ||
+ | $consulta->execute($parametros); | ||
+ | </source> | ||
+ | {{Actividad| | ||
+ | *Realiza un pequeño program en php que usando la extensión '''''PDO''''', realice las siguientes acciones | ||
+ | #Se conecte a la base de datos '''''dwes''''' | ||
+ | #insertamos un nuevo eleemntos o tupla en la tabla producto | ||
+ | #consultamos todos los productos y los visualizamos | ||
+ | #Hacemos otra consulta parametrizada de todos los productos de la tabla stock de una determinada tienda | ||
+ | ##Esta última acción primero usando '''''bindParam''''' y luego sin usarlo (pasando directamente el parámetro al método execute | ||
+ | |||
+ | <source lang=php> | ||
+ | <!DOCTYPE html> | ||
+ | <html> | ||
+ | <head> | ||
+ | <meta charset="UTF-8"> | ||
+ | <title></title> | ||
+ | </head> | ||
+ | <body> | ||
+ | <?php | ||
+ | $dns = "mysql:host=localhost; dbname=dwes"; | ||
+ | $user='root'; | ||
+ | $pass='root'; | ||
+ | $opciones= array( PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"); | ||
+ | //Realizamos una conexión básico pdo | ||
+ | $conexion = new PDO($dns, $user, $pass, $opciones); | ||
+ | if ($conexion) | ||
+ | echo "conexión realizada satisfactoriamente"; | ||
+ | else | ||
+ | echo "ohhhh!!!! no se ha conectado"; | ||
+ | |||
+ | //Ahora planteamos una sentencia de tipo insert | ||
+ | $sentencia = "insert into producto values('NEW_PRODUCTO12','NOMBRE_PRODUCTO','NOMBRE_CORTO','DESCRIPCION DESCRIPCION',10000,'MP3')"; | ||
+ | |||
+ | //Y planteamos tambión una sentencia select | ||
+ | $consulta ="select nombre_corto from producto"; | ||
+ | $filas= $conexion->exec($sentencia); | ||
+ | echo"Se ha insertado correctamene $filas"; | ||
+ | //$filas será un objeto del tipo PDOStatement | ||
+ | $filas= $conexion->query($consulta); | ||
+ | |||
+ | while ($fila=$filas->fetch()){ | ||
+ | echo "Se ha recuperado $fila[0]<br/>"; | ||
+ | } | ||
+ | $filas->closeCursor(); | ||
+ | $conexon=null; | ||
+ | //Ahora hacemos la consulta parametrizadas usando un objeto de la clase PDOStatement | ||
+ | //Hacemos el prepare | ||
+ | $sentencia= "Select producto from stock where tienda = :nom"; | ||
+ | |||
+ | $consulta = $conexion->prepare($sentencia); | ||
+ | $tienda =3; | ||
+ | |||
+ | //$consulta->bindParam(':nom',$tienda,PDO::PARAM_INT); | ||
+ | //$consulta->execute(); | ||
+ | //Podemos usar la opción de antes o esta otra | ||
+ | $consulta->execute(array(":nom"=>$tienda)); | ||
+ | //Ahora mostramos los resultados | ||
+ | while ($fila=$consulta->fetch()){ | ||
+ | echo "Visualizo el producto $fila[0]<br/>"; | ||
+ | |||
+ | } | ||
+ | ?> | ||
+ | </body> | ||
+ | </html> | ||
+ | |||
+ | </source> | ||
+ | |||
+ | }} | ||
+ | |||
===Control de excepticones=== | ===Control de excepticones=== | ||
+ | *A partir de la versión 5 se introdujo en PHP un modelo de excepciones similar al existente en otros lenguajes de programación: | ||
+ | #El código susceptible de producir algún error se introduce en un bloque '''''try - catch'''''. | ||
+ | <source lang=php> | ||
+ | try{ | ||
+ | //Instrucciones que pueden lanzar una excepción y | ||
+ | //puedo capturar en tiempo de ejecuciónj | ||
+ | |||
+ | }cathc(Exception $e){ | ||
+ | echo "Se ha producido una excepcion". $e->getMessage(); | ||
+ | } | ||
+ | </source> | ||
+ | #Cuando se produce algún error, se lanza una excepción utilizando la instrucción '''''throw'''''. | ||
+ | #Después del bloque try debe haber como mínimo un bloque catch encargado de procesar el error. | ||
+ | #Si una vez acabado el bloque try no se ha lanzado ninguna excepción, se continúa con la ejecución en la línea siguiente al bloque o bloques catch. | ||
+ | {{Actividad| | ||
+ | Haz un programa que si dividimos por cero pase una exepcion | ||
+ | |||
+ | <source lang=php> | ||
+ | try { | ||
+ | if ($divisor == 0) | ||
+ | throw new Exception("División por cero."); | ||
+ | $resultado = $dividendo / $divisor; | ||
+ | } | ||
+ | catch (Exception $e) { | ||
+ | echo "Se ha producido el siguiente error: ".$e->getMessage(); | ||
+ | } | ||
+ | </source> | ||
+ | }} | ||
+ | *PHP ofrece una clase base Exception para utilizar como manejador de excepciones. | ||
+ | *Esta clase implementa dos métodos generales que nos muestran información sobre la excepticon que se ha podido producir | ||
+ | *'''''getMessage'''''. Devuelve el mensaje, en caso de que se haya puesto alguno. | ||
+ | *'''''getCode'''''. Devuelve el código de error si existe. | ||
+ | *El caso de PDO define su propia clase de excepciones que deriva o hereada de la clase Exception | ||
+ | *Para el caso concreto de PDO, hay que configurar para que lance las excepciones, puediento esta configuración tomar los siguientes valores: | ||
+ | #PDO::ERRMODE_SILENT. No se hace nada cuando ocurre un error. Es el comportamiento por defecto. | ||
+ | #PDO::ERRMODE_WARNING. Genera un error de tipo E_WARNING cuando se produce un error. | ||
+ | #PDO::ERRMODE_EXCEPTION. Cuando se produce un error lanza una excepción utilizando el manejador propio PDOException. | ||
+ | |||
+ | *Vamos a ver como se utiliza: | ||
+ | *Primero activamos las excepciones, y luego ya se pueden utilizar | ||
+ | <source lang=php> | ||
+ | $dwes = new PDO("mysql:host=localhost; dbname=dwes", "dwes", "abc123."); | ||
+ | $dwes->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); | ||
+ | try { | ||
+ | $sql = "SELECT * FROM stox"; | ||
+ | $result = $dwes->query($sql); | ||
+ | //… | ||
+ | } | ||
+ | catch (PDOException $p) { | ||
+ | echo "Error ".$p->getMessage()."<br />"; | ||
+ | } | ||
+ | </source> | ||
+ | *En este caso que no existe la tabla nos diría | ||
+ | <source lang=php> | ||
+ | Error SQLSTATE[42S02]: Base table or view not found: 1146 Table 'dwes.stox' doesn't exist | ||
+ | </source> | ||
+ | *En el caso de mysqli usaríamos la clase mysqli_sql_exception que gestiona el tema de las excepciones | ||
+ | http://es.php.net/manual/es/class.mysqli-sql-exception.php | ||
+ | {{Actividad| | ||
+ | *Realicemos un fichero de conexión a base de datos que contenga las siguientes funciones | ||
+ | #'''''conectar'''''($bd, $usuario,$password) Retornará un objeto de la clase PDO si todo ok | ||
+ | #'''''consulta($sentencia,$parametros)''''' Retorna un objeto de la clase PDOStatement si todo ok, | ||
+ | ##Recibe dos argumentos, un string que será la consulta parametrizada, y un array con los valores para cada parámetro | ||
+ | #'''''Insertar($tabla,$valores)''''' | ||
+ | ##Recibe un string que es el nombre de tabla y un vector que serán los diferentes valores para cada campo de la tabla | ||
+ | ##Suponemos que se pasan los valores ok, si no, capturamos la excepción | ||
+ | }} | ||
+ | |||
+ | ===Filtros=== | ||
+ | *Qué es | ||
+ | *Para qué sirve | ||
+ | *Dónde aplicarlo | ||
+ | http://php.net/manual/es/ref.filter.php | ||
+ | *Concepto de escapar las comillas simples y dobles | ||
+ | *Ecapar las barras invertidas | ||
+ | http://php.net/manual/es/function.addslashes.php | ||
+ | |||
+ | |||
+ | |||
+ | ===Transacciones=== | ||
|} | |} |
Última revisión de 22:44 28 nov 2014
![]() |
Trabajo en proceso, espera cambios frecuentes. Tu ayuda y retroalimentación son bienvenidos. Ver página de charlas. |
![]() |
|