En la introducción ya hemos visto en que arquitecturas y tecnologías se apoyan tanto las páginas web como las aplicaciones web.
En este punto nos centraremos exclusivamente en la programación de páginas web en entorno servidor, en este caso con lenguaje PHP. También se les conoce como páginas dinámicas puesto que el contenido que presentan al usuario puede cambiar en función de las acciones de éste, no directamente porque el programador modifique su programación (como ocurre con las páginas estáticas). Así, en las páginas web dinámicas el usuario puede interactuar con el sitio web y modificar así la forma en que la información se presenta y también la propia información, puesto que puede gestionarla.
En este curso, hemos diferenciado además entre lo que se conoce como páginas web y aplicaciones web. Actualmente cada vez están más solapados los conceptos puesto que, el concepto de lo que se conocía antes como web ha ido cambiado. Así, sitios web como Facebook, Emodo o Twitter son auténticas aplicaciones (nos referimos siempre a sus sitios web) que funcionan directamente en el navegador web, por lo que pueden ser tratadas, claramente, como aplicaciones web. Por otro lado, tenemos sitios como blogs, periódicos online, . . ., que, aunque son dinámicos, se limitan practicamente a mostrar información al usuario (que puede interactur en mayor o menor medida). En este caso podemos hablar de páginas web (dinámicas). Eso si, entre unas y otras hay un sinfin de situaciones intermedias y hacen díficil decidir que hace que un sitio web pase a ser una aplicación web o viceversa.
Aunque este tema solamente trate sobre desarrollo en el lado servidor, obviamente necesitaremos trabajar también con HTML y CSS si queremos darle una apariencia minimamente correcta a nuestras páginas web a la hora de ser presentadas por el navegador. Para ello usaremos Bootstrap que es una librería de estilos para la creación rápida de sitios web. Además, en su web, podemos encontrar numerosos ejemplos sobre como estructurar una web. De esa manera, no tendremos que perder demasiado tiempo escribiendo y estructurando la parte visible de las webs y podremos centrarnos en la programación del lado servidor.
En cualquier caso, por si fuera necesario, en la sección Referencias se pueden encontrar guías de referencia de HTML y CSS, por si fuera necesario consultarlas.
Para la instalación y configuración de PHP, dispondremos de dos entornos:
apt
para la instalación del software necesario:santi@zenbook:$ apt-get install mysql-server mysql-client apache2 php7.0 php-mysql phpmyadmin
A continuación se puede ver un ejemplo de script PHP en el que sólo encontramos código en ese lenguaje. Es por eso que el fichero lo almacenaremos con extensión .php
<?php /* Esto es un comentario de varias lineas */ // Esto es un script PHP function sumar($numero1, $numero2) { $resultado = $numero1 + $numero2; return $resultado; } $suma_total = sumar(10, 15) echo "La suma es $suma_total";
También podemos tener ficheros que contengan tanto código PHP como HTML.
<!DOCTYPE html> <html> <head> <title>Mi primera página web</title> </head> <body> <?php echo "<p>Esta es mi primera página web</p>"; ?> <?php echo "<p>Hoy es " . date("d.m.Y") . "</p>"; ?> <p><?= "Esto es PH" ?></p> <a href="#">Esto será un enlace</a> <img src="#" alt="Esto será una imagen"/> </body> </html>
.php
obligatoriamente para que Apache lo sepa y se lo haga ejecutar al intérprete<?php
y no es necesario finalizar con etiqueta de cierre siempre y cuando el script sólo contenga código PHP. Si el fichero contiene PHP junto con HTML tendremos también que cerrar los bloques del primero con la etiqueta ?>
<?= ?>
que imprime por pantalla el valor constante o variable que se escriba entre las dos etiquetas (equivale a la instrucción echo
)exit(mensaje)
o die()
include(script.php)
, include_once(script.php)
, require(script.php)
o require_once(script.php)
. Las cuatro funciones permiten reutilizar el código que está escrito en el nombre del script que se pasa como parámetro pero presentan alguna diferencia<?php // Si falla produce un mensaje de WARNING include("funciones.php"); /* Funciona como la función include() pero comprueba que el fichero no se haya incluido ya */ include_once("funciones.php"); // Si falla produce un mensaje de ERROR y detiene el script require("funciones.php"); /* Funciona como la función require() pero comprueba que el fichero no se haya incluido ya */ require_once("funciones.php");
Estas funciones nos permitirán organizar nuestro sitio web de forma que aquellas partes que siempre se repiten o necesitemos utilizar en diferentes páginas puedan ser importadas y no tengamos que repetirlas.
Supongamos un sitio web compuesto de varios documentos (en principio HTML) como este donde cabecera y pie de la página se mantienen y sólo cambiaremos el contenido principal de la web. Probablemente incluso haya algún menú superior y/o lateral que también se mantenga o simplemente cambie para mostrar la sección en la que nos encontramos.
<!DOCTYPE html> <html lang="es"> <head> <meta charset="UTF-8"> <title>Título de la web</title> <link rel="stylesheet" type="text/css" href="css/bootstrap.css"/> </head> <body> <br/> <div class="container"> <h1>Información de actualidad</h1> <div class="list-group"> <a href="noticias.html" class="list-group-item">Noticias</a> <a href="deportes.html" class="list-group-item">Deportes</a> <a href="television.html" class="list-group-item">Televisión</a> <a href="series.html" class="list-group-item">Series</a> </div> <div class="container"> <p>Aqui irá el contenido de la web</p> <p>Y podrán ir muchas cosas dependiendo de la sección en la que esté</p> </div> <footer> © 2017 Ejercicio </footer> </div> </body> </html>
Está claro que siguiendo este esquema acabaremos teniendo varios documentos HTML (para noticias, deportes, television y series, al menos) que serán bastante parecidos al menos en cuanto a la maquetación de la web se refiere. Si que tendrán diferente contenido pero gran parte del código HTML se repetirá.
Así, si utilizamos PHP con su función include
o require
podremos organizar el código de una forma más óptima desde el punto de vista del desarrollador (el visitante nunca notará la diferencia) lo cual es muy importante sobre todo cuando el proyecto toma un tamaño considerable.
<?php if (isset($_REQUEST["id"]) $id = $_REQUEST["id"]; else $id = "noticias"; ?> <!DOCTYPE html> <html lang="es"> <head> <meta charset="UTF-8"> <title>Título de la web</title> <link rel="stylesheet" type="text/css" href="css/bootstrap.css"/> </head> <body> <br/> <div class="container"> <h1>Información de actualidad</h1> <div class="list-group"> <a href="?id=noticias" class="list-group-item">Noticias</a> <a href="?id=deportes" class="list-group-item">Deportes</a> <a href="?id=television" class="list-group-item">Televisión</a> <a href="?id=series" class="list-group-item">Series</a> </div> <div class="container"> <?php include($id . ".php"); ?> </div> <footer> © 2017 Ejercicio </footer> </div> </body> </html>
Hemos aprovechado la posibilidad de enviar parámetros en la URL para construir los hipervínculos de forma que apunten siempre a la misma web (en este caso index.php
) pero con un valor diferente para el parámetro id
. De esta forma, accediendo a dicho parámetro a través de la variable $_REQUEST
, podemos leerlo y cargar la sección que corresponda en cada caso.
Con esta estructura, los diferentes documentos que contengan el código de cada sección simplemente tendrán el contenido de la propia sección puesto que se incluyen dentro de una estructura que mantiene un maquetado, cabecera y pie común para todo el sitio web, por lo que el código del sitio web queda mucho más organizado y el mantenimiento de la web mucho más sencillo (imaginemos que simplemente queremos cambiar el año del Copyright de la web para el caso anterior).
En el repositorio de la asignatura se puede ver un ejemplo de esta estructura para separar el contenido de una página web. Es el ejemplo Ejercicio1 del repositorio servidor-ejercicios
//
o #
/*
y */
<!--
-->
.
Por otro lado, podemos tener código HTML para presentar información en el navegador. A estos ficheros los almacenaremos con la extensión .html. El navegador es capaz de interpretarlos puesto que 'entiende' el código HTML. Es por eso que además podemos abrirlos directamente con Firefox o Chrome directamente.
<!DOCTYPE html> <html> <head> <title>Mi primera página web</title> </head> <body> <p>Esta es mi primera página web</p> <a href="#">Esto será un enlace</a> <img src="#" alt="Esto será una imagen"/> </body> </html>
Pero hay que tener en cuenta que, a partir de ahora, podremos encontrarnos ficheros que contengan ambos lenguajes mezclados (PHP siempre aparecerá indicando su inicio y fin con las etiquetas correspondientes). En ese caso, siempre tendremos que almacenar el fichero con la extensión .php para indicarle a Apache que hay código (aunque sea una sola línea) que debe ser procesador por el intérprete de PHP.
A veces, por comodidad, y por no tener que modificar más adelante el nombre de ningún fichero, es posible almacenar código HTML bajo la extensión .php si luego tenemos pensado añadir dicho código. Apache puede pensar que hay código que ejecutar, se lo pasará al intérprete de PHP y, al no tener nada que hacer, devolverá el propio código HTML.
Por todo lo explicado anteriormente, estos ficheros (.php), no se pueden abrir directamente con ningún navegador. Éstos son incapaces de interpretar el código PHP. Hay que acceder directamente desde el propio servidor web (utilizando el navegador). Por ejemplo, al siguiente script PHP accederiamos a través de la siguiente URL http://localhost/hola.php
si el servidor web se encontrara instalado en nuestro propio equipo.
<!DOCTYPE html> <html> <head> <title>Mi primera página web</title> </head> <body> <p>Esta es mi primera página web</p> <a href="#">Esto será un enlace</a> <img src="#" alt="Esto será una imagen"/> </body> </html>
En este caso tenemos código PHP escrito junto con HTML.
<!DOCTYPE html> <html> <head> <title>Mi primera página web</title> </head> <body> <?php echo "<p>Esta es mi primera página web</p>"; ?> <?php echo "<p>Hoy es " . date("d.m.Y") . "</p>"; ?> <a href="#">Esto será un enlace</a> <img src="#" alt="Esto será una imagen"/> </body> </html>
Lo que tenemos que tener en cuenta es que nuestra página web HTML puede contener código PHP que deberá ser procesado por el intérprete. Si no lo contiene será Apache quién sirva la página directamente. En caso de que lo contenga, éste tendrá que pasar el fichero al intérprete, que será quien genere el código HTML resultante (por el camino quizás deba conectarse a una Base de Datos para recoger alguna información).
if <condicion1> { <sentencias1> } [elseif <condicion2> { <sentencias2> }] . . . [else { <sentencias3> }]
<?php $numero1 = 10; $numero2 = 20; if ($numero1 < $numero 2) { echo "numero1 es menor que numero2"; } elseif ($numero1 > $numero2) { echo "numero1 es mayor que numero2"; } else { echo "Los dos números son iguales"; }
for (<inicializacion>; <condicion>; <incremento>) { <sentencias> }
<?php $vector = array(1, 2, 3, 4); for ($i = 0; i < len($vector); $i++) { echo $vector[i] + "<br/>"; }
foreach (<elemento> in <array>) { <sentencias> }
<?php $vector = array(1, 2, 3, 4); foreach ($vector as $elemento) { echo $elemento . "<br/>"; }
Con la función array()
podemos crear arrays de diferentes maneras, según se muestra a continuación:
// Declarar un array vacío un_vector = array(); // Declarar un array con elementos otro_vector = array("uno", "dos", "tres"); // Declarar un array asociativo array_asociativo = array("DAW" => "Desarrollo de Aplicaciones Web", "DAM" => "Desarrollo de Aplicaciones Multiplataforma");
// Añade un elemento al final del array otro_vector[] = "cuatro";
// Añade un elemento al final del array array_push($otro_vector, "cinco"); // Añade un elemento al inicio del array array_unshift($otro_vector, "cero");
La función count()
permite contar el número de elementos de un array
echo "Número de elementos " . count($otro_vector);
La función sort()
ordena los elementos de un array de forma ascendente sobre el propio array.
sort($un_vector);
Tanto en el lado de la definición de la función como en el momento del paso de parámetros, podemos usar una características de PHP que permite tanto definir funciones con número variable de parámetros como pasar un array como parámetro haciendo que PHP acepte realmente cada uno de sus elementos como los parámetros de la misma, aunque ésta haya sido definida con un número fijo de los mismos 1)
En el primer caso podemos presentar la función indicando que acepta un número variable de parámetros. En este caso podemos pasarle tantos parámetros como queramos
<?php function sumar(...$numeros) { $resultado = 0; foreach ($numeros as $numero) { $resultado += $numero; } return $resultado; } echo sumar(34, 45, 3, 2, 12); ?>
En el siguiente caso tenemos una función con un número fijo de parámetros y podemos pasar los elementos de un array con el operador …
para que cada elemento del mismo ocupe la posición de uno de los parámetros
<?php function sumar($numero1, $numero2) { return $numero1 + $numero2; } $vector = array(10, 20); echo sumar(...$vector); ?>
<?php function sumar($numero1, $numero) { $resultado = $numero1 + $numero2; return $resultado; }
<?php include("funciones.php"); $resultado = sumar(3, 4); echo "<p>El resultado es " . $resultado . "</p>";
Lo primero que tendremos que tener en cuenta es que la configuración de acceso a la Base de Datos deberá estar en un fichero a parte y cada valor definido como una constante. De esta forma, cada vez que la queramos usar, este fichero podrá ser incluido para usar el valor de dichas constantes.
<?php define("DB_USUARIO", "santi"); define("DB_PASSWORD", "misupercontrasena"); define("DB_HOST", "localhost"); define("DB_NOMBRE", "nombrebasededatos");
Para el caso de webs que deban ser instaladas por los usuarios pueden resultar útil lanzar sentencias de creación de tablas, como el siguiente ejemplo donde un script PHP lanza la creación la Base de Datos, y a continuación la creación de una tabla.
<?php include("config/configuracion.php"); $conexion = new mysqli(DB_HOST, DB_USUARIO, DB_PASSWORD); if ($conexion->connect_error) { die("La conexión ha fallado " . $conexion->connect_error); } $sql = "CREATE DATABASE " . DB_NOMBRE; $sentencia = $conexion->prepare($sql); $sentencia->execute(); $conexion->select_db(DB_NOMBRE); $sql = "CREATE TABLE usuarios ( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY nombre VARCHAR(255) NOT NULL, apellidos VARCHAR(255), email VARCHAR(255), telefono VARCHAR(50) UNIQUE)"; $sentencia = $conexion->prepare($sql); $sentencia->execute(); $sentencia->close(); $conexion->close();
De forma similar podemos insertar registros en una Base de Datos utilizando sentencias SQL parametrizadas.
<?php include("config/configuracion.php"); $conexion = new mysqli(DB_HOST, DB_USUARIO, DB_PASSWORD, DB_NOMBRE); if ($conexion->connect_error) { die("La conexión ha fallado " . $conexion->connect_error); } $sql = "INSERT INTO usuarios (nombre, apellidos, email, telefono) VALUES (?, ?, ?, ?)"; $sentencia = $conexion->prepare($sql); $sentencia->bind_param("ssss","Santiago", "Faci", "email", 123456789); $sentencia->execute(); $sentencia->close(); $conexion->close();
En ocasiones será útil obtener el último id generado por una sentencia INSERT
cuando tengamos que registrar otra información y relacionarla con la primera. No podemos conocer con qué id tengo que relacionar la información puesto que el id no lo conoceré hasta una vez introducido el dato. Por ejemplo, si tengo que registrar un pedido y todos sus detalles, primero insertaré el pedido pero necesitaré el id generado para ese pedido puesto que todos los detalles estarán relacionados con el pedido a través de dicho campo.
Hay una solución rápida pero incorrecta que sería lanzar una consulta del estilo a SELECT MAX(id) FROM pedidos
para conocer el último id de esa tabla. La solución no es válida puesto que entre haber insertado el pedido y recoger el resultado de dicha consulta pueden haberse “colado” innumerables pedidos en la tabla (insertados por otros usuarios) y el valor que obtendría yo no sería el correcto.
Así, en PHP disponemos de un método, llamada insert_id
, al que puedo invocar para obtener el último id generado por mi conexión a la Base de Datos, por lo que ya no podrán “colarse” los ids generados por otros usuarios. Veamos un ejemplo:
. . . $conexion = new mysqli(DB_HOST, DB_USUARIO, DB_PASSWORD, DB_NOMBRE); . . . $sql = "INSERT INTO pedidos (descripcion, precio, fecha_pedido) VALUES (?, ?, ?, ?)"; $sentencia = $conexion->prepare($sql); $sentencia->bind_param("sds","Pedido del día", 120, "2017-11-21"); $sentencia->execute(); $id_pedido = $conexion->insert_id; while ($detalles as $detalle) { $sql = "INSERT INTO detalles (id_pedido, id_articulo, precio) VALUES " . "(?, ?, ?)"; $sentencia = $conexion->prepare($sql); $sentencia->bind_param("iid", $id_pedido, $detalle->id_articulo, $detalle->precio); $sentencia->execute(); } . . .
En este primer ejemplo veremos como lanzar consultas SQL sobre la Base de Datos y recoger los resultados con un cursor (variable $resultado
) para luego recorrer dicho cursor utilizando la función fetch_row()
que devuelve una fila del resultado, en cada iteración del bucle donde se encuentra. De la fila (la variable $fila
) podremos acceder a cada uno de los campos por la posición que ocupaban en la consulta (empezando con el valor 0
).
<?php include("config/configuracion.php"); $conexion = new mysqli(DB_HOST, DB_USUARIO, DB_PASSWORD, DB_NOMBRE); if ($conexion->connect_error) { die("La conexión ha fallado " . $conexion->connect_error); } $sql = "SELECT * FROM usuarios"; $sentencia = $conexion->prepare($sql); $sentencia->execute(); $resultado = $sentencia->get_result(); while ($fila = $resultado->fetch_row()) { echo "<li>" . $fila[1] . "</li>"; } $sentencia->close(); $conexion->close();
También podemos utilizar un array asociativo para almacenar el resultado de una consulta y de esa manera podremos acceder a cada campo de dicho resultado utilizando el nombre de la columna.
La forma de trabajar es la misma, solo que ahora obtendremos el valor de cada fila con la función fetch_assoc()
que devuelve un array asociativo de forma que podemos obtener el valor de cada columna a partir del nombre de ésta con la variable $fila
en este caso:
<?php include("config/configuracion.php"); $conexion = new mysqli(DB_HOST, DB_USUARIO, DB_PASSWORD, DB_NOMBRE); if ($conexion->connect_error) { die("La conexión ha fallado " . $conexion->connect_error); } $sql = "SELECT * FROM usuarios"; $sentencia = $conexion->prepare($sql); $sentencia->execute(); $resultado = $sentencia->get_result(); while ($fila = $resultado->fetch_assoc()) { echo "<li>" . $fila["nombre"] . "</li>"; } $sentencia->close(); $conexion->close();
También puede ser necesario parametrizar nuestras consultas en base a un parámetro pasado por la URL, un dato introducido en un formulario, . . . de forma que podamos crear scripts más genéricos y polivalentes. En ese caso debemos usar las consultas parametrizadas de forma que una vez “preparada” la consulta podamos inyectarle nosotros los parámetros que se han indicado con el caracter ?
. Al asociaar los parámetros con sus valores, utilizando la llamada al método bind_param
asociaremos cada parámetro con un valor, indicando ademas el tipo del parámetro con los siguientes caracteres:
s
: Si es una cadena (string
)d
: Si es un número con decimales (double
)i
: Si es un número entero o booleano (integer
) <?php include("config/configuracion.php"); $conexion = new mysqli(DB_HOST, DB_USUARIO, DB_PASSWORD, DB_NOMBRE); if ($conexion->connect_error) { die("La conexión ha fallado " . $conexion->connect_error); } $sql = "SELECT * FROM usuarios WHERE id = ?"; $sentencia = $conexion->prepare($sql); $sentencia->bind_param("i",12); $sentencia->execute(); $resultado = $sentencia->get_result(); while ($fila = $resultado->fetch_row(MYSQLI_ASSOC)) { echo "<li>" . $fila["nombre"] . "</li>"; } $sentencia->close(); $conexion->close();
Y una vez vistas varias formas de lanzar consultas contra la Base de Datos, podemos aprovechar para ver alguna forma de organizar el código de forma que no tengamos que escribir todas las instrucciones de conexión, preparación de la consulta, parámetros, etc cada vez que hagamos una consulta.
Por ejemplo, podríamos crear una función a la que pasando la sentencia escrita en lenguaje SQL y los parámetros (si los hubiera) y que fuera ésta la que conectara con la Base de Datos, preparara el paso de parámetros (en caso de que haya), lanzara la consulta y devolviera los resultados.
function lanzar_consulta($sql, $parametros = array()) { $conexion = new mysqli(DB_HOST, DB_USUARIO, DB_PASSWORD, DB_NOMBRE); $sentencia = $conexion->prepare($sql); if (!empty($parametros)) { $tipos = ""; foreach ($parametros as $parametro) { if (gettype($parametro) == "string") $tipos = $tipos . "s"; else $tipos = $tipos . "i"; } $sentencia->bind_param($tipos, ...$parametros); } $sentencia->execute(); $resultado = $sentencia->get_result(); $sentencia->close(); $conexion->close(); return $resultado; }
Así, cada vez que queramos lanzar una consulta sobre la Base de Datos simplemente tendríamos que hacer algo asi:
// Aqui utilizaríamos la función include() para incluir el fichero que contiene // la declaración de la función . . . $sql = "SELECT nombre, apellidos FROM usuarios"; $resultado = lanzar_consulta($sql); . . .
Y en el caso de que la consulta estuviera parametrizada:
// Aqui utilizaríamos la función include() para incluir el fichero que contiene // la declaración de la función . . . $ciudad = . . . $descuento = . . . . . . $sql = "SELECT nombre, apellidos FROM usuarios WHERE ciudad = ? AND descuento = ?"; $resultado = lanzar_consulta($sql, array($ciudad, $descuento); . . .
Cuando los resultados de una consulta generan una página demasiada extensa resulta bastante molesto por lo que se suele emplear la técnica de paginación para mostrar un número limitado de resultados por página incluso cuando hay muchos más. La solución pasa por generar una serie de enlaces a modo de páginas que permitan al usuario navegar entre los resultados de una manera más cómoda. También es posible incluso mostrar al usuario la posibilidad de ver todos los resultados en una sola página si él lo prefiere. En ocasiones esas páginas podrán ser solamente botones que permitan avanzar a la pagina anterior o a la página posterior y en otras ocasiones nos pueden mostrar un listado completo de todas las páginas (o no si éste es a su vez demasiado extenso) para que a su vez podamos avanzar más rápidamente saltándonos páginas intermedias. Esta es la solución que mostraremos aqui pero hay que tener en cuenta que no es la única como ya he comentado.
Lo primero que haremos será definir una constante que almacene el número de resultados que se mostrarán por página. Hay que tener en cuenta que este valor puede tener un valor por defecto pero también podemos dejar que sea el usuario quien lo escoja.
<?php . . . define("TAMANO_PAGINA", 5); . . .
Y ahora, a la hora de mostrar los resultados, hay que añadir el código necesario tanto para el cálculo del total de páginas necesarias para mostrar los resultados, como para mostrar sólamente los resultados que procedan. Además, habrá que dejar unos enlaces (o botones según se prefiera) que permitan al usuario navegar por las páginas de los resultados:
<?php // Esta variable indica que página hay que cargar if (isset($_REQUEST["pagina"])) $pagina = $_REQUEST["pagina"]; else $pagina = 0; . . . . . . // Primero calculamos cuántos resultados hay $sql = "SELECT COUNT(*) FROM articulos"; . . . $total_articulos = . . . // Calcula el número de páginas que hacen falta $total_paginas = $total_articulos / TAMANO_PAGINA; . . . // Se traen sólo aquellas filas que se van a mostrar (según la página) $sql = "SELECT nombre, descripcion FROM articulos LIMIT " . $pagina * TAMANO_PAGINA . " ," . TAMANO_PAGINA; . . . // Prepara los botones que paginan los resultados for ($i = 0; $i <= $total_paginas; $i++) { ?> <a href="?pagina=<?= $i ?>"><?= $i + 1 ?></a> <?php } ?>
A la hora de modificar registros, tal y como hemos hecho en el caso anterior, utilizamos consultas parametrizadas donde nosotros mismos debemos luego inyectar el valor de los parámetros. En este caso, al tratarse de dos parámetros, una cadena ('s' de 'string') y un entero ('i' de 'integer'), lo indicamos como se puede ver en el siguiente fragmento de código:
<?php include("config/configuracion.php"); $conexion = new mysqli(DB_HOST, DB_USUARIO, DB_PASSWORD, DB_NOMBRE); if ($conexion->connect_error) { die("La conexión ha fallado " . $conexion->connect_error); } $sql = "UPDATE usuarios SET email = ? WHERE id = ?"; $sentencia = $conexion->prepare($sql); $sentencia->bind_param("si","nuevo@email.com", 123); $sentencia->execute(); $sentencia->close(); $conexion->close();
De forma muy similar a los casos anteriores, podemos eliminar registros:
<?php include("config/configuracion.php"); $conexion = new mysqli(DB_HOST, DB_USUARIO, DB_PASSWORD, DB_NOMBRE); if ($conexion->connect_error) { die("La conexión ha fallado " . $conexion->connect_error); } $sql = "DELETE usuarios WHERE id = ?"; $sentencia = $conexion->prepare($sql); $sentencia->bind_param("i", 123); $sentencia->execute(); $sentencia->close(); $conexion->close();
Una vez conocidas las operaciones que podemos realizar sobre una Base de Datos (MySQL en este caso, aunque será muy similar para cualquier SGBD), a la hora de la verdad conviene organizar lo mejor posible el código de nuestra aplicación para que a la hora de acceder a la Base de Datos lo hagamos de la mejor manera posible. Por un lado desde el punto de vista del rendimiento y por otro lado desde el punto de vista de organizar y estructurar bien el código de nuestro proyecto. Es por eso que resulta muy recomendable desde este momento comenzar a utilizar el paradigma de Programación Orientado a Objetos con el que podemos contar en un lenguaje PHP para organizar, en este caso, todo el código que realiza accesos a la Base de Datos.
A continuación se muestra un ejemplo genérico de cómo podría organizarse una clase donde concentrar todo el código que realice acceso a Base de Datos de forma que pueda utilizarse desde cualquier documento PHP que necesite bien consulta, insertar, modificar o eliminar algún dato, o realizar cualquier otra operación en alguna tabla.
<?php /** Clase que permite comunicarse con la Base de Datos */ class Db { private $conexion; /** * Constructor. Permite conectar con la Base de Datos */ function __construct() { $this->conectar(); } /** * Conecta con la Base de Datos */ function conectar() { // Suponemos que en un fichero de configuración hemos definido // unas constantes con la configuración de la conexión $this->conexion = new mysqli(HOST_BD, USUARIO_BD, CONTRASENA_BD, NOMBRE_BD); } /** * Desconecta de la Base de Datos */ function desconectar() { $this->conexion->close(); } /** * Obtiene el último generado en la última sentencia INSERT * \return El id que se generó */ function ultimo_id() { return $this->conexion->insert_id; } /** * Lanza cualquier tipo de sentencia con o sin parámetros * \param sql La sentencia a ejecutar * \param parametros Los parámetros, si los hay * \return El resultado de la consulta */ function lanzar_consulta($sql, $parametros = array()) { $sentencia = $this->conexion->prepare($sql); if (!empty($parametros)) { $tipos = ""; foreach ($parametros as $parametro) { if (gettype($parametro) == "string") $tipos = $tipos . "s"; else $tipos = $tipos . "i"; } $sentencia->bind_param($tipos, ...$parametros); } $sentencia->execute(); $resultado = $sentencia->get_result(); $sentencia->close(); return $resultado; } }
A la hora de programar un formulario, si queremos emplearlos para que nuestros usuarios suban ficheros al sitio web, lo primero que tendremos que tener en cuenta es la configuración en nuestro fichero php.ini
y comprobar que está acorde con nuestras necesidades. En la siguiente tabla aparecen las tres directivas más importantes, para que sirven y qué valores pueden tomar.
Un formulario web tiene dos partes:
Así, supongamos un formulario para iniciar sesión en una página web. Por una parte tendríamos el código HTML que lo define:
<form action="procesar.php" method="post"> <fieldset> <legend>Datos Personales</legend> Login: <br/> <input type="text" name="nombre" size="30"/><br/> Contraseña:<br/> <input type="password" name="contrasena" size="15"/><br/> </fieldset> <input type="submit" value="Enviar"/> </form>
Y por otra parte, el correspondiente script PHP que lo procesa. En este caso, simplemente se muestran los dos campos que el usuario ha introducido como ejemplo de cómo recibir la información en el lado servidor utilizando la variable $_REQUEST
<?php $nombre = $_REQUEST["nombre"]; $contrasena = $_REQUEST["contrasena"]; echo "Hola " . $nombre;
En el caso de los formularios para subir ficheros, hay que tener en cuenta que tendremos que definir el tipo de codificación del mismo para indicar que se adjuntarán archivos:
<!DOCTYPE html> <html> <body> <form action="subir_fichero.php" method="post" enctype="multipart/form-data"> Select image to upload: <input type="file" name="fichero" id="fichero"> <input type="submit" value="Upload Image" name="submit"> </form> </body> </html>
Y en el lado del servidor, habrá que recuperar el valor de los campos del formulario y el del archivos o archivos adjuntos, que además tendrán que ser copiados a la ruta destino que haya definida en la web para la subida de archivos:
<?php if (isset($_FILES["fichero"])) { $directorio = "ficheros/"; // Establece la ruta final del fichero (manteniendo su nombre original) $ruta_final = $directorio . basename($_FILES["fichero"]["name"]); // Ruta donde se encuentra temporalmente el fichero pendiente de la ubicación final $fichero_temporal = $_FILES["fichero"]["tmp_name"]; // Mueve el fichero de su ubicación temporal a la ruta definitiva en el servidor move_uploaded_file($fichero_temporal, $ruta_final); echo "<p>El fichero se ha subido correctamente</p>"; } ?>
Si fuera necesario, también podemos obtener la siguiente información de un fichero que ha sido enviado a través de un formulario:
// Obtiene el tamaño del fichero en bytes $tamano = $_FILES["fichero"]["size"]; // Obtiene el tipo del fichero (la extensión) $tipo = $_FILES["fichero"]["type"];
También es posible enviar información oculta al usuario en un formulario. Es la forma que disponemos de enviar información fija independientemente de la que se introduzca en los campos. En ese caso el campo del formulario se define como hidden
y se fija su valor en la definición del propio campo con el atributo value
.
Más adelante en el script PHP podrá ser recuperado como un campo más.
<form action="procesar.php" method="post"> <fieldset> <legend>Datos Personales</legend> Login: <br/> <input type="text" name="nombre" size="30"/><br/> Contraseña:<br/> <input type="password" name="contrasena" size="15"/><br/> <input type="hidden" name="accion" value="login"/> </fieldset> <input type="submit" value="Enviar"/> </form>
Y al procesar dicho formulario:
<?php $nombre = $_REQUEST["nombre"]; $contrasena = $_REQUEST["contrasena"]; $accion = $_REQUEST["accion"]; echo "Hola " . $nombre;
En este caso vamos a utilizar jQuery y un plugin para trabajar con formulario llamado jQuery Form Plugin. Con ellos podremos procesar formularios de una manera más cómoda.
Aqui tenemos un ejemplo de un formulario en el que el usuario debe introducir dos valores para dar de alta su usuario en una web. El formulario se ejecuta con Ajax utilizando la librería de jQuery y el plugin mencionado anteriormente por lo que, desde el punto de vista del desarrollador, el mensaje de respuesta del script PHP que procesa los datos (el action
) nos viene devuelto y podemos pintarlo en la web simplemente utilizando la función echo
en dicho script. Será jQuery quién recogerá el valor y nos lo trairá de vuelta al documento HTML donde se encuentra el formulario.
<!DOCTYPE html> <html lang="es"> <head> <meta charset="UTF-8"> <title>Ejemplo de formularios</title> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.js"></script> <script src="http://malsup.github.com/jquery.form.js"></script> <script> $(document).ready(function() { $('#formulario').ajaxForm({ success:function(response) { // Se puede emitir una alerta alert("El usuario ha sido dado de alta correctamente"); // También se puede escribir la respuesta del script en una capa $('#mensaje').html(response); // Y resetear el formulario $('#formulario').each(function() { this.reset(); }); } }) }); </script> </head> <body> <h1>Ejemplo de formulario</h1> <form id="formulario" action="alta_usuario.php" method="post"> <fieldset> <legend>Datos Personales</legend> Nombre: <br/> <input type="text" name="nombre" size="30"/><br/> E-mail:<br/> <input type="text" name="email" size="30"/><br/> </fieldset> <input type="submit" value="Enviar"/> </form> <div id="mensaje"></div> </body> </html>
Aqui podemos ver con más detalle el código javascript utilizado, donde se indica qué hacer en caso de que el formulario se ejecuta correctamente (success
).
$(document).ready(function() { $('#formulario').ajaxForm({ success:function(response) { // Se puede emitir una alerta alert("El usuario ha sido dado de alta correctamente"); // También se puede escribir la respuesta del script en una capa $('#mensaje').html(response); // Y resetear el formulario $('#formulario').each(function() { this.reset(); }); } }) });
Y, finalmente, el script PHP que procesa el formulario simplemente necesita pintar en pantalla el resultado y será jQuery quién lo recoja y lo muestre donde hemos indicado utilizando javascript.
<?php $nombre = $_POST["nombre"]; $email = $_POST["email"]; . . . // Aqui se da de alta al usuario, por ejemplo . . . // Si hay algún error podemos emitir un mensaje directamente echo "Se ha producido un error"; . . . // Si todo va bien podemos notificarlo al usuario echo "El usuario " . $nombre . " ha sido dado de alta correctamente";
A la hora de validar los campos de un formulario, podemos comprobar, utilizando de nuevo el plugin jQuery Form Plugin, si los valores introducidos en los formularios son correctos antes de que éstos sean enviados. Es una buena forma de evitar tener que enviar de vuelta los mensajes de error validando los formularios en el lado servidor desde PHP. Ahora podemos validar el formulario antes de que sea enviado
Veamos un ejemplo que podríamos aplicar para el caso anterior.
$(document).ready(function() { $('#formulario').ajaxForm({ beforeSubmit:function(data, form) { if (!form[0].email.value) { $('#mensaje').html("Debes indicar un email"); return false; } } }) });
También podemos validar formularios utilizando jQuery Validation Plugin de una forma muy sencilla. Basta con marcar las etiquetas input
como required
, asignarles id
(para poder personalizar los mensajes) e invocar la función validate()
del plugin
<!DOCTYPE html> <html lang="es"> <head> <meta charset="UTF-8"> <title>Ejemplo de formularios</title> <script src="jquery-3.2.1.min.js"></script> <script src="jquery.validate.min.js"></script> </head> <body> <h1>Ejemplo de formulario</h1> <form id="formulario" action="alta_usuario.php" method="post"> <fieldset> <legend>Datos Personales</legend> Nombre: <br/> <input type="text" name="nombre" size="30"/><br/> E-mail:<br/> <input type="text" name="email" size="30"/ required><br/> </fieldset> <input type="submit" value="Enviar"/> </form> <div id="mensaje"></div> <script> $("#formulario").validate({ messages: { nombre: " Debes introducir tu nombre", email: " Debes introducir tu email" } }); </script> </body> </html>
En la parte javascript se puede ver como se invoca el método validate()
para lanzar la validación del formulario y como se han personalizado los mensajes de error para cada uno de los campos (utilizando el id
de cada uno de ellos)
$("#formulario").validate({ messages: { nombre: " Debes introducir tu nombre", email: " Debes introducir tu email" } });
El protocolo HTTP es el protocolo encargado de la transferencia de hipertexto, utilizado para la transferencia de los documentos HTML desde el servidor hasta el cliente. Puesto que se trata de un protocolo sin estado, la transferencia de cada documento se realiza de forma independiente, sin mantener ninguna relación con cualquier transferencia que se haga inmediatamente anterior o posteriormente. Por tanto, este protocolo es incapaz de saber si es el mismo cliente quién está solicitando una serie de documentos (páginas web) o se trata de clientes diferentes.
Es por eso que necesitaremos algún mecanismo si queremos ser capaces de mantener la sesión de un usuario o saber de alguna manera que éste ha realizado alguna visita previa a la actual. En este caso, mediante PHP como lenguaje de desarrollo del lado servidor, veremos cómo llevar a cabo este tipo de operaciones.
En el desarrollo web existen dos formas para mantener el estado:
También existen algunas otras diferencias entre cookies y sesiones como por ejemplo el hecho de que las sesiones se eliminen al cerrar el navegador mientras que las cookies pueden permanecer durante mucho tiempo en el equipo del cliente (y a pesar de haber cerrado el navegador).
Antes de comenzar con el uso de sesiones en nuestros proyectos PHP tendremos que comprobar que éste está correctamente configurado para el uso de las mismas. Para eso, tendremos que echar un vistazo al fichero de configuración php.ini
y comprobar que está fijado un valor para la variable session.save_path
(que por defecto será /tmp
).
. . . session.save_path="/tmp" . . .
La forma más habitual de iniciar una sesión en un sitio web es hacerlo a través de un formulario que permita identificar al usuario que va a iniciarla. En nuestro ejemplo preparamos un formulario sencillo donde un visitante necesita introducir su nombre de usuario y contraseña (previamente se habrá registrado) para comenzar la sesión en el sitio web.
Suponemos que una vez iniciada su sesión, tendrá acceso a una zona del sitio web que vendrá personalizada. En caso contrario no tendría sentido solicitar que se identificara.
<form action="login.php" method="post"> <fieldset> <legend>Login</legend> Usuario: <br/> <input type="text" name="usuario" size="30"/><br/> Contraseña:<br/> <input type="password" name="contrasena" size="15"/><br/> </fieldset> <input type="submit" value="Entrar"/> </form>
El script que inicia la sesión tendrá que hacerlo utilizando el método session_start()
. En ese momento el servidor almacenará la información necesaria para mantenerla mientras el usuario no decida cerrarla (veremos como se hace más adelante).
Además podemos aprovechar para almacenar variables de sesión (se almacenan en $_SESSION
) de forma que podamos también recordar cierta información que pueda ser útil durante la misma. Una vez iniciada la sesión y recogida la información podemos redirigir al usuario a la página de inicio de nuevo o bien a una zona privada.
<?php session_start(); $_SESSION["usuario"] = $_POST["usuario"]; $_SESSION["fecha"] = date() header("location: index.php");
Hay que tener en cuenta que todas las páginas web del sitio que necesiten conocer el estado de la sesión deberán incluir la llamada a start_session
para mantenerla y además habrá que comprobar que se tiene acceso al menos a la variable de sesión que utilizamos para identificar al usuario. En nuestro caso, en el script que procesa el formulario de login habíamos almacenado el nombre del usuario en la variable de sesión $_SESSION[“usuario”]
por lo que comprobamos que ésta exista para poder asegurar que el visitante actual se encuentra identificado. En caso contrario lo redireccionaremos fuera de la zona privada.
Hay que tener en cuenta que almacenando el valor del usuario que tienen iniciada la sesión permite a su vez personalizar la información que se muestra o bien permitir hacer determinadas acciones en función de quién sea ese usuario o bien del rol que tenga en el sitio web (si lo hemos almacenado en otra variable de sesión o podemos ir a consultarlo a la Base de Datos a partir de conocer el nombre de usuario).
<?php session_start(); if (!isset($_SESSION["usuario"])) { header("location: no_permitido.php"); } ?> <!DOCTYPE html> <html> <head> </head> <body> <p>Bienvenido a tu sesión de usuario <?= $_SESSION["usuario"]; ?></p> <p>Puedes pasarte por el sitio web <a href="otra_pagina.php">aqui</a></p> <p>También puedes <a href="logout.php">salir</a></p> </body> </html>
Cualquier otra página que necesite mantener el estado deberá iniciar de la misma forma, manteniendo la sesión con session_start
y comprobando que el visitante la tiene iniciada.
<?php session_start(); if (!isset($_SESSION["usuario"])) { header("location: no_permitido.php"); } ?> <!DOCTYPE html> <html> <head> </head> <body> <p>Hola de nuevo <?= $_SESSION["usuario"]; ?></p> </body> </html>
Y finalmente, el script que procese (bien a través de un botón de un formulario o bien un simple enlace) la salida de la sesión tendrá que iniciarla para luego eliminar toda la información de la sesión (session_unset
) y luego eliminar la propia sesión del servidor (session_destroy
).
A partir de este momento, el servidor web dejará de recordar al visitante como un usuario con sesión a todos los efectos.
<?php session_start(); session_unset(); session_destroy() header("location:index.php");
El lenguaje PHP también incorpora el paradigma de Orientación a Objetos y es posible crear clases de la que luego instanciar objetos de forma bastante similar a como se hace en lenguajes como Java.
A continuación una clase con 3 atributos de diferente visibilidad, un constructor y algunos métodos con el objetivo de conocer la sintaxis con este paradigma.
<?php class Producto { public $marca; protected $precio; private $ingredientes; function __construct($marca, $precio) { $this->marca = $marca; $this->precio = $precio; $this->ingredientes = array(); } function anadir_ingrediente($ingrediente) { array_push($this->ingredientes, $ingrediente); } function numero_ingredientes() { return count($this->ingredientes); } } $colacao = new Producto("Nestle", 10); echo $colacao->marca; echo $colacao->precio; echo $colacao->numero_ingredientes();
El primer paso para implementar unas buenas medidas de seguridad es no mostrar información excesiva a potenciales atacantes. Por eso, desde el fichero de configuración de PHP (php.ini
), podemos activar los logs de errores y desactivar el mostrarlos por pantalla. Mostrar los fallos cuando éstos se produzcan puede ayudar a los posibles atacantes a conocer mejor nuestro sistema, lo que facilitará que encuentres vulnerabilidades.
. . . log_errors = On display_errors = Off # En entorno de desarrollo/pruebas puede estar a On . . .
La inyección SQL es un tipo de ataque que consiste en inyectar código SQL a las aplicaciones que trabajan con Base de Datos para conseguir más información de que la éstas proporcionan (por motivos de privilegios), volcar la Base de Datos, realizar cambios, autenticarse, entre otros. La inyección de SQL se realiza, por ejemplo, añadiendo cierto código SQL en los formularios que debemos cumplimentar para acceder a cierta información o al autenticarnos. Se trata de aprovechar despistes o fallos en la programación que permitan ejecutar dichas consultas libremente. Así, podremos realizar cualquier operación directamente sobre la Base de Datos, dependiendo de cómo esté implementada el sitio o aplicación web.
En este caso, vamos a tratar con un tipo de inyección SQL que nos va a permitir autenticarnos en un sitio web conociendo solamente el usuario.
Suponemos que tenemos una Base de Datos de usuarios como la que se muestra a continuación
mysql> select * from usuarios; +----+---------+------------------------------------------+-------+ | id | usuario | password | email | +----+---------+------------------------------------------+-------+ | 1 | santi | 9d4e1e23bd5b727046a9e3b4b7db57bd8d6ee684 | NULL | +----+---------+------------------------------------------+-------+ 1 row in set (0.00 sec)
Además, disponemos de un formulario para iniciar sesión y se nos solicita el usuario y contraseña:
<!DOCTYPE html> <html> <head> <title>Formulario de inicio de sesión</title> </head> <body> <form action="db.php" method="post"> <fieldset> <legend>Datos Personales</legend> Login: <br/> <input type="text" name="usuario" size="30"/><br/> Contraseña:<br/> <input type="password" name="password" size="15"/><br/> </fieldset> <input type="submit" value="Enviar"/> </form> </body> </html>
Y aqui tenemos el script que se ha desarrollado para el inicio de sesión donde se validan usuario y contraseña y si coinciden, se muestra un mensaje confirmando que el usuario tiene acceso. Nos podemos fijar ya que los parametros de la consulta están simplemente concatenados, lo que es claramento un síntoma de script inyectable por SQL.
<?php $usuario = $_POST["usuario"]; $password = sha1($_POST["password"]); $conexion = new mysqli("localhost", "root", "", "programacionweb"); if ($conexion->connect_error) { } $sql = "SELECT * FROM usuarios WHERE usuario = '$usuario' AND password = '$password'"; echo "<p>$sql</p>"; # Sólo como depuración, para ver la inyección $resultado = $conexion->query($sql); if ($resultado->num_rows == 1) { echo "<p>Login OK!</p>"; } else { echo "<p>Acceso no permitido</p>"; } $conexion->close();
Ahora mismo nuestro script de login es vulnerable al menos a un tipo de ataque de inyección SQL muy extendido y reconocido. Si un usuario, que sólo conoce el nombre de usuario (pero no la contraseña), realiza este ataque, podrá iniciar sesión. Se trata simplemente de inyectar código SQL que será añadido al código que el propio script ejecuta. De esa forma podemos cambiar el comportamiento del script y trabajar de forma distinta para la que este diseñado.
Aqui se puede ver como el script muestra (a modo de depuración) la consulta SQL ejecutada y el resultado ha sido que se le ha permitido el acceso porque se ha validado dicha consulta como verdadera.
Para subsanar este tipo de ataque, una de las principales medidas que se deben de realizar es parametrizar las consultas SQL utilizando los propios mecanismos que nos proporciona PHP.
Así, el script de login, parametrizando, en vez de concatenando los parámetros, deja de ser vulnerable para este ataque. Basta realizar unos pocos cambios tal y como se muestra en el siguiente ejemplo (este script reemplazaría al otro) y puede volver a probarse el formulario. Ahora no será posible realizar este tipo de inyección.
<?php $usuario = $_POST["usuario"]; $password = sha1($_POST["password"]); $conexion = new mysqli("localhost", "root", "", "programacionweb"); if ($conexion->connect_error) { } $sql = "SELECT * FROM usuarios WHERE usuario = ? AND password = ?"; echo "<p>$sql</p>"; $sentencia = $conexion->prepare($sql); $sentencia->bind_param("ss", $usuario, $password); $sentencia->execute(); $sentencia->store_result(); if ($sentencia->num_rows == 1) { echo "<p>Login OK!</p>"; } else { echo "<p>Acceso no permitido</p>"; } $conexion->close();
Para la creación de informes en PHP existen multitud de librerías que disponen del API necesaria para la generación de documentos (PDF, por ejemplo) a partir de los datos que nosotros le proporcionemos (desde la Base de Datos, por ejemplo).
Una de esas librerías es FPDF que, aunque es muy sencilla, es muy recomendable para empezar a trabajar con informes en PHP. Para informes más completos donde queramos generar documentos con estilos más complejos podemos utilizar otras librerías como TCPDF.
Una vez descargado de su página web tendremos que copiar los ficheros necesarios (fpdf.php
, fpdf.css
y las carpetas fonts
y makefonts
) dentro de la carpeta donde guardemos las librerías que queremos usar en nuestro proyecto.
Veamos primero un ejemplo muy sencillo de la librería FPDF que nos va a permitir crear un documento PDF a partir de un texto. Conviene tener en cuenta que la llamada al método Output()
genera el fichero PDF por lo que el siguiente código acaba lanzando el documento al navegador para cargarlo o descargarlo directamente.
<?php require('fpdf.php'); $pdf = new FPDF(); $pdf->AddPage(); $pdf->SetFont('Arial','B',16); $pdf->Cell(40,10,'Mi primer informe'); $pdf->Output(); ?>
PHP dispone de numerosas funciones internas que se pueden usar directamente, sin necesidad de importar nada. Aqui se listarán, por categorías, las más utilizadas.
Nombre | Descripción |
---|---|
abs(numero) | Valor absoluto |
ceil(numero) | Redondeo al alza |
floor(numero) | Redondeo a la baja |
is_nan(valor) | Comprueba si un valor es un numero |
round(numero,precision) | Redondea con la precisión indicada |
sqrt(numero) | Calcula la raíz cuadrada |
Ejemplos:
$numero = abs(-4); # $numero -> 4 $numero = ceil(3.1); # $numero -> 4 $numero = floor(3.9); # $numero -> 3 $es_numero = is_nan("hola") # $es_numero -> False $numero = round(1.93847, 2) # $numero -> 1.94 $numero = sqrt(9) # $numero -> 3
Nombre | Descripción | Más info |
---|---|---|
implode([separador], array) | Une los elementos de un array en una cadena | implode() |
explode([separador], cadena) | Separa los elementos de una cadena en un array | explode() |
strlen(cadena) | Devuelve la longitud de una cadena | strlen() |
substr(cadena, inicio, [longitud]) | Devuelve parte de una cadena | substr() |
trim(cadena) | Elimina los espacios en blanco a ambos lados de una cadena | trim() |
Ejemplos:
$vector = array("uno", "dos", "tres"); $todos = implode(",", $vector); # $todos -> 'uno,dos,tres' $vector = explode(",", "uno,dos,tres") # $vector[0] -> 'uno' $vector[1] -> 'dos' . . . $longitud = strlen("manzana"); # $longitud -> 7 $cadena = substr("murcielago", 2); # $cadena -> 'rcielago' $cadena = substr("murcielago", 2, 3); # $cadena -> 'rci' $cadena = trim(" manzana "); # $cadena -> 'manzana'
Nombre | Descripción | Más info |
---|---|---|
date_create(fecha) | Crea una instancia de una fecha dada | date_create() |
date_diff(fecha1, fecha2) | Devuelve la diferencia entre dos fechas | date_diff() |
date_format(fecha,formato) | Formatea una fecha según un patrón | date_format() |
date(patron, [fecha=time()]) | Devuelve una fecha (o la de hoy) formateada según un patrón | date() |
strtotime(fecha) | Pasa una cadena a formato de fecha UNIX | strtotime() |
Ejemplos:
$fecha1 = date_create('2017-09-10'); $fecha2 = date_create('2017-09-17'); $diferencia = datediff(fecha1, fecha2) # $diferencia -> 7 $fecha = date_format(date(), "d-m-Y"); # $fecha -> '20-09-2017' $fecha = date("d.m.Y"); # $fecha -> '20.09.2017' // Cómo convertir una fecha extraída de un datepicker (jQuery) a formato MySQL $fecha = date("Y-m-d", strtotime("20-10-2010")); # $fecha -> '2010-10-20'
<?php /** * Clase que representa a los artículos de la tienda */ class Articulo { /** Proveedor del artículo */ public proveedor; . . . /** * Calcula los gastos de envio en función del destino * \param destino El destino del artículo * \return Los gastos de envío */ function calcular_gastos_envio($destino) { . . . return gastos; } . . . }
santi@zenbook:$ apt-get install doxygen graphviz <code bash> <code bash> santi@zenbook:$ doxygen -g config.dox
. . . INPUT = . . .
santi@zenbook:$ doxygen config.dox
En el repositorio de Github de servidor-ejercicios se pueden ir encontrando todos los ejemplos que vayamos haciendo en clase
© 2018-2019 Santiago Faci