Diferencia entre revisiones de «Usuario:ManuelRomero/php/BasesDatos»
De WikiEducator
< Usuario:ManuelRomero | php
(→Injecciones SQL) |
|||
(28 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 389: | Línea 388: | ||
#http://es.wikipedia.org/wiki/Inyecci%C3%B3n_SQL | #http://es.wikipedia.org/wiki/Inyecci%C3%B3n_SQL | ||
#http://www.w3schools.com/sql/sql_injection.asp | #http://www.w3schools.com/sql/sql_injection.asp | ||
+ | *Otras entradas un poco cuestionables por finalidad ??? | ||
+ | #http://foro.elhacker.net/tutoriales_documentacion/tutorial_de_inyeccion_sql_sql_injection-t98448.0.html | ||
+ | #http://www.mclibre.org/consultar/php/lecciones/php_db_inyeccion_sql.html#L2641 | ||
+ | #http://blog.netrunners.es/tabla-de-trucos-para-inyeccion-de-sql/ | ||
}} | }} | ||
− | *A continuación y usando el ejemplo anterior de '''''acceso''''' vamos a probar a realizar | + | *A continuación y usando el ejemplo anterior de '''''acceso''''' vamos a probar a realizar un sencillo ataques sql. |
#Entrar en la plataforma sin tener acceso | #Entrar en la plataforma sin tener acceso | ||
− | + | ||
− | + | ||
===Entrar en la plataforma sin tener acceso=== | ===Entrar en la plataforma sin tener acceso=== | ||
+ | *Entramos en una página y vemos el siguiente acceso | ||
[[Archivo:miAcceso.png]] | [[Archivo:miAcceso.png]] | ||
+ | *Como no sabemos el usuario ni contraseña probamos a ver si se puede hacer una inserción no controlada | ||
+ | *Como programadores esperamos que en el código haya algo del estilo, como es nuestro caso | ||
+ | <source lang=php> | ||
+ | $nombre=$_POST['usuario']; | ||
+ | $pass=$_POST['pass']; | ||
+ | |||
+ | $consulta="select * from usuarios where nombre = \"$nombre\" and pass = \"$pass\" "; | ||
+ | $resultado = $conexion->query($consulta); | ||
+ | </php> | ||
+ | *Si todo fuera normal y nombre fuera por ejemplo "maría" la consulta que se envía al servidor sería | ||
+ | <source lang=php> | ||
+ | select * from usuarios where nombre = "maria" | ||
+ | </source> | ||
+ | *Esta consulta si existe el usuario maría nos retornará una tupla, si no no devolverá ninguna. | ||
+ | *Pero si añadimos más cosas obtendremos segura una respuesta, por ejemplo si en el codigo $nombre="maria or \"1\"= \"1\" " | ||
+ | *Entonces la consulta quedaría | ||
+ | <source lang=php> | ||
+ | select * from usuarios where nombre = "maria" or "1"="1" | ||
+ | </source> | ||
+ | *Que nos devolverá todas las filas | ||
+ | *Así que si introducimos estos datos | ||
+ | [[Archivo:miAccesoInjeccion.png]] | ||
+ | *Entramos al sistema sin conocer usuario y contraseña | ||
+ | [[Archivo:accesoInjectado.png]] | ||
===Consultas preparadas=== | ===Consultas preparadas=== | ||
Línea 402: | 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 411: | 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 442: | 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 464: | Línea 491: | ||
}} | }} | ||
− | ===Consultas preparadas que retornan valores | + | ===Consultas preparadas que retornan valores=== |
*En caso de que la consulta preparada retorne valores se recogen con el método '''''bind_result'''' | *En caso de que la consulta preparada retorne valores se recogen con el método '''''bind_result'''' | ||
*Este método recibirá variables en los que se almacenarán los valores | *Este método recibirá variables en los que se almacenarán los valores | ||
*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 477: | 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 | ||
http://php.net/manual/es/class.mysqli-stmt.php | http://php.net/manual/es/class.mysqli-stmt.php | ||
+ | {{Actividad| | ||
+ | *Modifica el ejercicio anterior usando consultas parametrizadas | ||
+ | }} | ||
{{Actividad| | {{Actividad| | ||
− | * | + | *Vamos a trabajar con la base de datos de la tienda |
− | * | + | *Lo primero usando la herramienta workbench generamos el modelo de tablas de la base de datos dwes y la analizamos |
+ | *Crea una página web en la que se muestre el stock existente de un determinado producto en cada una de las tiendas. | ||
+ | *Para seleccionar el producto concreto utiliza un cuadro de selección dentro de un formulario en esa misma página. | ||
+ | * Puedes usar como base los siguientes ficheros css y plantilla adjuntos. | ||
+ | *Añade la opción de modificar el número de unidades del producto en cada una de las tiendas. | ||
+ | *Utiliza una consulta preparada para la actualización de registros en la tabla stock. | ||
+ | *No es necesario tener en cuenta las tareas de inserción (no existían unidades anteriormente) y borrado (si el número final de unidades es cero). | ||
}} | }} | ||
<!-- | <!-- | ||
Línea 508: | Línea 544: | ||
--> | --> | ||
+ | ==Bases de datos con PDO== | ||
+ | ===Qué es PDO=== | ||
+ | *La extensión PDO (PHP Data Objects) permite acceder a diferentes gestores de bases de datos utilizando las misma funciones. | ||
+ | *Esto es una gran ventaja frente a la extensión vista anteriormente mysqli, | ||
+ | *PDO nos abstrae de forma completa el sistema gestor que se utiliza. | ||
+ | *Como comentamos en el tema anterior, necesitaremos el driver concreto dependiendo del sistema gestor de bases de datos. | ||
+ | *Esto es lo único que tendremos que cambiar en nuestro programa para que funcione en uno u otro gestor de bases de datos, sin tener que cambiar nada del sql. | ||
+ | *En PHP 5 existen drivers para acceder a las bases de datos más populares (MySQL, Oracle, MS SQL Server, PostgreSQL, SQLite, Firebird, DB2, Informix, etc). | ||
+ | *En el siguiente enlace podemos ver los controladores de PDO que soporta directamente php. | ||
+ | http://es.php.net/manual/es/pdo.drivers.php | ||
+ | |||
+ | *En esta lección se explica el acceso a MySQL y SQLite mediante PDO. La extensión PDO no evalúa la correción de las consultas SQL. | ||
+ | |||
+ | ===Establecer conexión con PDO=== | ||
+ | *Para establecer una conexión lo que hacemos es instanciar un objeto de la clase PDO | ||
+ | <source lang=php> | ||
+ | $conexion = new PDO(...); | ||
+ | </source> | ||
+ | El constructor tien 4 parámetros de los cuales sólo el primero es obligatorio | ||
+ | ;Origen de datos (DSN). | ||
+ | :Este parámetro es un string que la información del controlador del driver que voy a utilizar y se especifica de la siguiente manera | ||
+ | controlador:parametro1=dato1;parametro2=datos...parametron=daton | ||
+ | :Los parámetros a especificar dependerá del controlador que vamos a utilizar, en general me informarán del controlador del driver que voy a utilizar como por ejemplo el nombre o dirección IP del servidor, el nombre de la base de datos). | ||
+ | :Por ejemplo en el caso del controlador mysql | ||
+ | <source lang=php> | ||
+ | $conexion = new PDO('mysql:host=localhost;dbname=dwes', ...); | ||
+ | </source> | ||
+ | ;Nombre de usuario | ||
+ | ;Contraseña del usuario. | ||
+ | ;Opciones de conexión, almacenadas en forma de array. | ||
+ | *Muchas de las opciones de conexión dependerán del driver que vayamos a utilizar | ||
+ | *Por ejemplo con mysql podemos verlas aquí http://php.net/manual/es/ref.pdo-mysql.php | ||
+ | (Ver dentro de cada página de controladores http://php.net/manual/es/pdo.drivers.php) | ||
+ | ====Conxión con mysql==== | ||
+ | *En el caso de mysql en parámetro DNS tendríamos los siguientes datos | ||
+ | *'''''host''''' Nombre o dirección IP del servidor. | ||
+ | *'''''port''''' Número de puerto TCP en el que escucha el servidor. | ||
+ | *'''''dbname''''' Nombre de la base de datos. | ||
+ | *'''''unix_socket''''' Socket de MySQL en sistemas Unix. | ||
+ | *Como podemos ver en el ejemplo anterior, no todos los datos del parámetro DNS son obligatorios, podemos establecer la conexión con '''''host''''' y '''''dbname'''''. | ||
+ | *Respecto a las opciones de conexión permiten establecer varios cuestiones | ||
+ | *Una vez establecida la conexión se pueden consultar/acutalizar valores de opciones de la conexión usando los métodos | ||
+ | getAtribute(int $atributo); | ||
+ | setAtribute(int $atributo, mixed $valor); | ||
+ | *Podemos ver los atributos en la página http://es.php.net/manual/es/pdo.setattribute.php http://es.php.net/manual/es/pdo.getattribute.php | ||
+ | ===Realizar consultas con PDO=== | ||
+ | *En el caso de PDO, se diferencias las consultas que retornan datos (SELECT) y las que actúan sobre el contendio de los datos (INSERT, UPDATE, DELETE) | ||
+ | ;INSERT, OPDATE, DELETE | ||
+ | *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 | ||
+ | <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=== | ||
+ | *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=== | ||
+ | *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. |
|