|
|
(3 revisiones intermedias por el mismo usuario no mostrado) |
Línea 20: |
Línea 20: |
| </div> | | </div> |
| | | |
− | {{MRM_Punto Clave|Title=Acciones básicas que hemos de aprender| | + | {{MRM_Puntos clave|Title=Acciones básicas que hemos de aprender| |
| ;Para trabajar con una base de datos, siempre hemos de seguir una serie de acciones | | ;Para trabajar con una base de datos, siempre hemos de seguir una serie de acciones |
| | | |
− | *1.- Concetarnos a la base de datos
| + | ;1.- Concetarnos a la base de datos |
| Esto será crear una instancia de un objeto de conexión | | Esto será crear una instancia de un objeto de conexión |
− | *2.- Verificar que la conexión se ha realizado
| + | ;2.- Verificar que la conexión se ha realizado |
| Si, por el motivo que fuera, no nos hemos podido conectar,generalmente: | | Si, por el motivo que fuera, no nos hemos podido conectar,generalmente: |
| 1.- Informaremos de ello | | 1.- Informaremos de ello |
| 2.- Cerraremos la conexión | | 2.- Cerraremos la conexión |
− | *3.- Realizaremos las operativas que necesitemos
| + | ;3.- Realizaremos las operativas que necesitemos |
| Ejecutaremos sentencias SQL y recogeremos el resultado de la consulta | | Ejecutaremos sentencias SQL y recogeremos el resultado de la consulta |
| Generalmente informaremos de algo al usuario de la aplicación | | Generalmente informaremos de algo al usuario de la aplicación |
− | *4.- Cerraremos la conexión
| + | ;4.- Cerraremos la conexión |
| Un aspecto que puede pasar desapercibido, pero muy importante | | Un aspecto que puede pasar desapercibido, pero muy importante |
| }} | | }} |
Línea 169: |
Línea 169: |
| | | |
| <div class="slide"> | | <div class="slide"> |
− | =====DML===== | + | ====Ejecutando sentencias SQL: DML (insert, delete, update, select)==== |
| *En SQL sabemos que tenmos tres tipos de lenguajes DDL, DML, DCL | | *En SQL sabemos que tenmos tres tipos de lenguajes DDL, DML, DCL |
| *Nos vamos a centrar en el DML, Leguane de maniputación de datos | | *Nos vamos a centrar en el DML, Leguane de maniputación de datos |
Línea 359: |
Línea 359: |
| *En el segundo caso nos retornará un booleano y para leer los datos deberemos usar o '''''store_result''''' o '''''use_result''''' según veamos a continuación. | | *En el segundo caso nos retornará un booleano y para leer los datos deberemos usar o '''''store_result''''' o '''''use_result''''' según veamos a continuación. |
| </div> | | </div> |
| + | *El método '''''query''''' con una sentencia de tipo '''''select''''' como parámetro, nos retorna un objeto de la clase mysqli_result. Esta clase (recurso) implemente la interfaz '''''Traversable''''', lo que le hace iterable en los datos que contiene. |
| + | *Esta clase contiene el resultado de la consulta como un conjunto de filas, pero no lo tiene como un atributo visible, si no como parte de los métodos que tenemos disponibles para obtenerlo (los metodos fetch_xxxx) |
| <div class="slide"> | | <div class="slide"> |
| | | |
Mysqli
Para trabajar con las extensiones, las usaremos siempre orientadas a objetos, aunque tengan
la correspondiente funcionalidad en el lenguaje estructurado.
- Para recordar muy brevemente posemos usar el siguiente enlace
http://www.desarrolloweb.com/articulos/1540.php
- Uso básico de un recurso de tipo mysqli
- Recordamos que para crear una nueva instancia de una clase usamos el operador new
- Para acceder a los diferentes métodos del objeto instaciado, usamos el operador de indirección ->
$miObjeto->metodo($parametros);
Acciones básicas que hemos de aprender
- Para trabajar con una base de datos, siempre hemos de seguir una serie de acciones
- 1.- Concetarnos a la base de datos
Esto será crear una instancia de un objeto de conexión
- 2.- Verificar que la conexión se ha realizado
Si, por el motivo que fuera, no nos hemos podido conectar,generalmente:
1.- Informaremos de ello
2.- Cerraremos la conexión
- 3.- Realizaremos las operativas que necesitemos
Ejecutaremos sentencias SQL y recogeremos el resultado de la consulta
Generalmente informaremos de algo al usuario de la aplicación
- 4.- Cerraremos la conexión
Un aspecto que puede pasar desapercibido, pero muy importante
|
Mysql y su extensión mysqli para php
- CONECTARNOS A LA BASE DE DATOS
- A continuación iremos viendo como implementar las acciones básicas en el lenguaje
- Conectarse
- Para conectarse a una base de datos , creamos una instacia de la clase mysqli de la forma
$miConexion = new mysqli(....);
- Extensión Mysqli
- El constructor de la clase puede recibir hasta 5 parámetros, de los cuales 4 se suelen usar con bastante frecuencia
- $host nombre o ip del equipo (null o localhost, identificaría el equipo actual).i
- $usario es el usuario de la base de datos
- $pass
- $nombreBD
- $puerto
- $shocket
- Ejemplo new mysqli(...)
$host="localhost"
$usuario="manolo";
$pass="romero";
$nombreBD="alumnos";
$miConexion = new mysqli ($host,$usuario,$pass,$nombreBD);
if ($miConexion==null)
echo"No se ha podido crear el objeto.
Seguramente no tiene instalada la extensión mysqli.
Prueba a instalar apt install php-mysql ";
else
echo "Objeto creado";
(: Pruena a ver el contenido del objeto con var_dump, así podrás observar los atributos que tenemos disponibles. Son todos muy intuitivos y los iremos viendo a lo largo de este tema.)
- mysqli(...)
- Esta función retorna el recurso de la conexión.
Tip: Aunque hablemos de mysqli como una clase, en realidad es una clase especial conocida como recurso.
Un recurso a diferencia de una clase no se puede serializar para pasar entre scripts.
- Para gestionar los errores de la conexión, debemos de usar los atributos:
- connect_errno: Número o códiog del error que se ha producido en la conexión. 0 implica que no hay error.
- connect_error:Descripción del error en forma de string. "" (cadena vacía) es la descripción cuando no ha habido error en la conexión.
de la clase mysqli.
- El echo de que se pueda instanciar o el objeto de la clase, no implica que se haya realizado la conexión.
- Este atributo aporta información sobre el error o contiene null si no se ha producido ninguno.
- En el código anterior
if ($miConexion->connect_error) {
echo "ERROR;
echo "Error: Fallo al conectarse a MySQL debido a: \n";
echo "Errno: " . $mysqli->connect_errno . "\n";
echo "Error: " . $mysqli->connect_error . "\n";
}
- Para ver información sobre la conexión se puede usar los atributos $server_info o $host_info
Resumen
$conesion= new mysqli($host,$user,$pass,$bd);
$conesion->conect_error
$conesion->conect_errno
$conesion->server_info
$conesion->host_info
|
- Opciones por defecto
- Hay muchas opciones de mysqli que se pueden configurar en el fichero php.ini, no es algo que normalmente se modifique, pero por curiosidad las comentamos aquí.
- Aquí tenemos alguna de ellas
- mysqli.allow_persistent
- Permite crear conexiones persistentes.
- mysqli.default_port
- Número de puerto TCP predeterminado a utilizar cuando se conecta al Servidor de base de datos.
- mysqli.reconnect
- Indica si se debe volver a conectar automáticamente en caso de que se pierda la conexión.
- mysqli.default_host.
- Host predeterminado a usar cuando se conecta al servidor de base de datos.
- mysqli.default_user.
- Nombre de usuario predeterminado a usar cuando se conecta al servidor de base de datos.
- mysqli.default_pw
- Contraseña predeterminada a usar cuando se conecta al servidor de base de datos.
Cerrar una base de datos
- Cerrar conexión
- Cuando ya no vamos a utilizar más la conexión la cerramos para liberar recursos.
- Es importante hacer esta acción de forma explícita
Cambiar la base de datos
- Si hemos seleccionado una base de datos, o no hemos seleccionado ninguna y queremos cambiar a otra
$miConexion->select_db("nombre_base_datos");
- Cuando ya no vamos a usar un recurso, conviente y repito CONVIENE, liberarlo.
Tip: Es muy importante liberar un recurso reservado una vez que ya no se vaya a usar mas.
Ejecutando sentencias SQL: DML (insert, delete, update, select)
- En SQL sabemos que tenmos tres tipos de lenguajes DDL, DML, DCL
- Nos vamos a centrar en el DML, Leguane de maniputación de datos
- Podemos clasificar en dos tipos de clúsulas:
- las que no devuelven registros de datos (INSERT, DELETE, UPDATE)
- Generalmente retornan un entero que es el número de filas aceptadas o un booleano que indica si se realizó no la operación
- DML
- Las que pueden retornan una colección de filas (SELECT), generalmente conocidas como cursor.
- En mysqli podemos enviar cualquiera de estas claúsulas con el método query
INSERT, UPDATE Y DELETE: Método query(...)
El método query, es un método de la clase mysqli que permite enviar una sentencia sql a la base de datos con la que tengamos conexión. En función del tipo de consulta, el método nos puede devolver los siguientes valores:
- Booleano (con las sentencias Insert, Update, Delete); indica si la acción se realizó o no correctamente.
- mysqli_result (con la sentencia Select); si la consulta es de tipo select, el método retornará un conjunto de filas (0 o más); Dispondremos de esta información en un objeto del la clase mysql_result. Esta clase la estudiamos posteriormente.
Hay que tener en cuenta que este método modifica el objeto de la clase mysqli pudiendo afectar a los siguiente atributos:
Atributos que puede modificar query()
- $affected_rows. Número de filas modificadas por la acción.
- $error, $errno. En caso de producir un error la sentencia.
- $insert_id Devuelve el id autogenerado que se utilizó en la última inserción.
|
Resumen
//Me conecto a la base de datos
$miConexion = new mysqli("localhost", "root", "root", "dwes");
//Me preparo sentencias
//Actuaré sobre la tabla tienda (ver BD anterior)
//Tiene los campos cod (autogenerado de forma incremental),
//nombre y tlf (ambos de tipo varchar)
$sentenciaInsert="INSERT INTO tienda (nombre, tlf)
VALUES ('Tienda centro', '111-155226')";
$sentenciaDelete="DELETE FROM tienda
WHERE nombre = 'Tienda centro' ";
$sentenciaUpdate="UPDATE tabla tienda
SET nombre = 'Tienda principal'
WHERE nombre = 'Tienda centro'";
//Hago una consulta de tipo insert
$resultado=miConexion->query($sentenciaInsert)
if($resultado){
echo"Se han insertado $miConexion->affected_rows
filas en esta acción <br />";
echo "en la inserción se asignó el id autogenerado $miConexion->insert_id
<br />";
}
|
Tip: Muy importante observa el tema de las comillas, los valores de las instrucciones sql sin son de tipo varchar deben de ir entre comillas
'Tip: Muy importante para la BD es igual comilla simple '''''' que comillas dobles "
Pregunta
Qué pasa si en nombre de la tienda es por ejemplo Technology's house
- Habría que escapar ese carácter
|
Inserción de datos
- Realiza una aplicación para insertar datos en una tabla llamada usuarios
- Insertaremos Nombre, Password y edad
- Verificaremos la insercción accediendo a la base de datos con phpmyadmin
- El password que esté cifrada
|
Escapar caracteres
Consiste en que de una forma automática si una cadena de caracteres tiene comillas, que estás queden escapadas para que formen parte de la cadena de caracteres y no especifique delimitación de la cadena.
Método para escapar cadenas
- Es un método de la clase mysqli
string mysqli_real_scape_string ( mysqli $conexion, string $cadena_a_escapar )
También se puede usar como método de la clase
$conexion = new mysqli(..);
$cadena = $conexion->real_scape_string(....);
|
|
Escapar caracteres
|
|
- suponemos que tenemos una tabla llamada acciones que tiene el campo descripcion y cod_usuario
- Quiero insertar este valor para descripcion como muestra el siguiente código:
//...
$descripción = "I don't want go animal's house"
//Esta asignación es correcta
//...
$consulta = "INSERT INTO acciones VALUES (1, '$descripcion')"
//...
si yo miro el contenido de la variable $consulta que es lo que pasare al método query()
INSERT INTO acciones VALUES (1, 'I don't want go animal's house')
- Esto a la hora de insertar me generará un error, ya que el gestor interpreta que el contenido para el campo descripcion es 'I don'
- Para evitar esto yo querría que el valor de $descripcion estuviera escapado
INSERT INTO acciones VALUES (1, 'I don\'t want go animal\'s house')
se puede conseguir
//...
$descripción = $conexion->real_scape_string("I don't want go animal's house");
//...
$consulta = "INSERT INTO acciones VALUES (1, '$descripcion')"
//...
|
'Tip: Alternativamente al método de la clase mysqli, podemos usar con metodología estructurada la función mysql_real_scape_string()
Tip: Observa el tema de las comillas, los valores de las instrucciones sql sin son de tipo varchar deben de ir entre comillas
$miConexion->query($sentenciasDelete);
$resultado =$miConexion->query($sentenciaDELETE);
if ($resultado){
echo "Se han borrado $miConexion->affected_rows filas ";
}
$miConexion->query($sentenciasUpdate);
$resultado = $miConexion->query($sentenciaUPDATE);
if ($resultado){
echo "Se han actualizado $miConexion->affected_rows filas ";
}
</sourece>
</div>
<div class="slide">
<source lang=php>
$miConexion->query($sentenciasInsert);
$resultado = $miConexion->query($sentenciaINSERT);
if ($resultado){
echo "Se han insertado $miConexion->affected_rows filas ";
}
- Observemos su uso en el ejemplo
//Establecemos la conexión
$miConexion = new mysqli('localhost', 'manolo', '12345.', 'baseDatosPrueba');
//Capturamos un posible error
$error = $miConexion->connect_errno;
//En caso de error informamos de ello
if ($error == null) {
$resultado = $miConexion->query('DELETE FROM stock WHERE unidades=0');
if ($resultado) {
print "<p>Se han borrado $miConexion->affected_rows registros.</p>";
}
}
$miConexion->close();
}
Clausula SELECT con query
- Tenemos dos maneras de realizar consultas con mysqli
- query
- real_query
- En el primero caso el método nos retorna un cursor que será de la clase mysqli_result.
- En el segundo caso nos retornará un booleano y para leer los datos deberemos usar o store_result o use_result según veamos a continuación.
- El método query con una sentencia de tipo select como parámetro, nos retorna un objeto de la clase mysqli_result. Esta clase (recurso) implemente la interfaz Traversable, lo que le hace iterable en los datos que contiene.
- Esta clase contiene el resultado de la consulta como un conjunto de filas, pero no lo tiene como un atributo visible, si no como parte de los métodos que tenemos disponibles para obtenerlo (los metodos fetch_xxxx)
Método query
- Una vez que tenemos los datos almacenados debemos saber acceder.
- Tenemos 4 formas de poder acceder a los datos según usemos un método u otro.
- Cuando hablamos de acceder a los datos, estamos estableciendo la forma de extraer cada fila, registro o tupla resultado de ejecutar la consulta.
- fetch_array()
- Va obteniendo cada registro como un array
- Este array podemos usar tanto de forma indexada, como asociativa (con el nombre del campo)
- fetch_assoc()
- En este caso el array que retorna es asociativo
- fetch_row()
- En este caso el array que retorna es indexado
- fetch_object()
- En este caso en lugar de retornar un array, retorna un objeto, donde cada campo son los diferentes atributos de ese objeto
- En todos los casos cada vez que leemos un elemento de mysqli_result, lo que por comparativa sería un cursor, vamos avanzando al siguiente. Cuando hayamos leído todos retornaría null
Actividad
- Obtén todos los registros de la tabla familia
- visualízalos en una tabla usando los tres modos de lectura de datos vistos anteriormente
|
- Para liberar un recurso del tipo mysqli_result, usamos el método free();
- La clase mysqli_result, además de los métodos vistos tiene un par de atributos interesantes
- int $field_count;
- Nos dice cuantas columnos tiene el query actual
- int $num_rows;
- Nos dice cuantas filas hemos obtenido con la consulta
- Tenemos una lista completa
http://es.php.net/manual/es/class.mysqli-result.php
Resumen
$conexion= new mysqli($host,$user,$pass,$bd);
if ($conexion->connect_errno==null){
$resultado = $conexion->query($consulta);
$numFilas = $resultado->num_rows;
$numCampos = $resultado->fields_count;
echo "La consulta ha retornado $numFilas filas con $numCampos columnas";
$fila = $resultado->fetch_array();
while ( $fila){
echo"El valor del primer campo es $fila[0]";
$fila = $resultado->fetch_array();
}
$resultado->free();
$conexion->close();
}
|
Actividad
Haciendo una consulta del tipo select * from producto where pvp < 200, realiza un código que visualizce en una tabla los resultados
|
Transacciones
Definición
- Una transacción es un conjunto de acciones u operaciones que
- Esta se realizan contra una base de datos de modo que o bien se realizan correctamente todas
- o no se realiza ninguna
|
- Supongamos que hacemos una transferencia bancaria; cuando menos implica descontar dinera de una cuenta e ingresaro en otra
- Transacciones
- Ahora supongamos que nada mas descontar el dinero de una cuenta se cae la luz y se apaga el servidor
- Esto creará una inconsistencia en la base de datos
- Por defecto en mysqli cada acción con la base de datos es una transacción en sí misma, pero esto se puede modificar
$conexion = new mysqli(..);
$conexion->autocommit(false);
.....
- Si se ha desactivado el autocommit, para terminar una transacción debemos usar los métodos commit o rollback
$conexion = new mysqli(..);
$conexion->autocommit(false);
.....
if (CondicionOK){
//Terminamos la transacción confirmando todas las acciones sobre la base de
//datos desde que se inició la transacción
$conexion->commit();
}else{
//Terminamos la transacción deshaciendo todas
//las acciones sobre la base de datos desde que se inició la
//transaccion, y dejando la base de datos igual que estaba al principio
$conexion->rollback();
}
Actividad
Ejercicio de transacciones
|
Injecciones SQL
- Es un problema de seguridad importante, que hay que conocer y evitar
- Existe mucha documentación al respecto, en general podemos afirmar que un buen conocimiento de SQL proporcina herramientas tanto para poder establecer este tipo de ataques, como para podernos prevenir de ellos.
- Aportamos referenicas de web que nos pueden interesar consultar
- Otras entradas un poco cuestionables por finalidad ???
- 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
- Entramos en una página y vemos el siguiente acceso
- 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
$nombre=$_POST['usuario'];
$pass=$_POST['pass'];
$consulta="select * from usuarios where nombre = \"$nombre\" and pass = \"$pass\" ";
$resultado = $conexion->query($consulta);
- Si todo fuera normal y nombre fuera por ejemplo "maría" la consulta que se envía al servidor sería
select * from usuarios where nombre = "maria"
- Esta consulta si existe el usuario maría nos retornará una tupla, si no no devolverá ninguna.
- Inyecciones sql
- 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
select * from usuarios where nombre = "maria" or "1"="1"
- Que nos devolverá todas las filas
- Así que si introducimos estos datos
- Entramos al sistema sin conocer usuario y contraseña
Consultas preparadas
- Una consulta preparada consiste en establecer una consulta como si fuera una variable y ejecutarla posteriormente tantas veces como sea necesario.
- Estas consultas se almacenan en el servidor y están listas para ser ejecutadas cuando sea necesario. El servidor solo tiene que analizarlas una vez
- Para trabajar con consultas preparadas, debemos usar la clase mysqli_stmt, e inicializarla con el método stmt_init
$conexion = new mysqli('localhost', 'dwes', 'abc123.', 'dwes');
//Preparo el objeto $consulta para crear consultas preparadas en él
$consulta = $conexion->stmt_init();
Los pasos para trabajar con consultas preparadas son:
- Preparar la consulta en el servidor MySQL utilizando el método prepare.
- Ejecutar la consulta, tantas veces como sea necesario, con el método execute.
- Una vez que ya no se necesita más, se debe ejecutar el método close.
$consulta = $conexion->stmt_init();
$consulta->prepare('INSERT INTO familia (cod, nombre) VALUES ("TABLET", "Tablet PC")');
$consulta->execute();
$consulta->close();
$conexion->close();
Parametrizar las consultas preparadas
- El uso real de las consultas preparadas es que los valores que pasas se asignen antes de ejectuar la consulta.
- La idea es preapara la consulta sin indicar los valores.
- Asignar los valores y ejectuar la consulta cuantas veces sea necesario.
- Veamos el proceso
- Parametrizar la consulta
- Consiste en indicar en la consulta preparada en lugar de los valores, signos de interrogación ?
- En el caso anterior
$consulta->prepare('INSERT INTO familia (cod, nombre) VALUES (?,?);
- Ahora habría que asigar los valores. Para ello usamos el método bind_param'
bind_param(tipoDatos, variables_con_los_valores)
- Este método recibe dos tipos de parámetros
- El primero es una cadena de caracteres, donde cada carácter especifica el tipo de valor que va a recibir cada uno de los valores esperados en la consulta.
- s: cadena de caracteres
- i: número entero
- d: número float
- b: valor binario (BLOB (binary large object))
- Consultas preparadas
- En nuestro caso como va a recibir en los dos parámetros cada uno una cadena de caracteres sería "ss"
- El segundo grupo sería cada uno de los valores.SIEMPRE hay que especificar variables
- En el ejemplo que estamos siguiendo
$consulta = $conexion->stmt_init();
$consulta->prepare('INSERT INTO familia (cod, nombre) VALUES (?, ?)');
$cod_producto = "TABLET";
$nombre_producto = "Tablet PC";
$consulta->bind_param('ss', $cod_producto, $nombre_producto);
- Insisto en que siempre hay que especificar variables, nunca directamente valores.
- Vemos el siguiente ejemplo:
$consulta->bind_param('ss', 'TABLET', 'Tablet PC'); // Genera un error
Resumen
$conexion = new mysqli(...);
$consulta = $conexion->stmt_init();
$consulta->prepare(...sentencia ... con ???)
$consulta->bind_param('s-i-b-d(tipo_de_valores)',
valores_en_variables_respectivos_a_????');
$consulta->execute();
$consulta->close();
$conexion->close();
|
Consultas preparadas que retornan valores
- 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
- Para recorre el conjunto de valores, usamos el método fectch()
- Vemos el siguiente ejemplo
- Consultas preparadas que generan valores
$consulta = $conexion->stmt_init();
$consulta->prepare('SELECT producto, unidades FROM stock WHERE unidades<2');
$consulta->execute();
$consulta->bind_result($producto, $unidades);
while($consulta->fetch()) {
print "<p>Producto $producto: $unidades unidades.</p>";
}
$consulta->close();
$conexion->close();
Práctica de tienda
- 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.
|
Práctica de tienda
- 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)
- Tampoco las de borrado (si el número final de unidades es cero).
|