Contexto


Durante las últimas semanas has caminado un largo trayecto conociendo las piezas que necesitas para crear programas con PHP. A partir de este momento empezarás a unir estas piezas de manera coherente.

Habrá nuevos comandos, keywords y técnicas que tal vez no has visto, pero en su momento se dará la explicación que solucionará tus dudas. Pero primero vas a utilizar phpMyAdmin para crear una base de datos MySQL que permita acceder a información remota.

En este tema sólo se mostrará cómo crear una base de datos básica y algunos queries básicos, pero en la segunda etapa de este curso obtendrás mayor y mejor información acerca de MySQL.

Explicación


6.1 Incorporar MySQL y PHP

Al instalar XAMPP en tu computadora tienes acceso a MySQL y a phpMyAdmin, programas incluidos en el paquete de instalación. MySQL es una opción popular de base de datos para uso en aplicaciones web, es de código abierto y ampliamente utilizado en aplicaciones LAMP. Por otro lado phpMyAdmin es una herramienta gratuita y de código abierto escrita con PHP que sirve para crear y administrar bases de datos de MySQL a través de una interfaz web.

Con estas herramientas puedes crear, modificar o borrar bases de datos, tablas, ejecutar consultas SQL (Structured Query Language) y administrar usuarios y permisos entre otras acciones. Recuerda que puedes construir bases de datos desde la consola de Windows, para conocer más sobre ello puedes consultar aquí y aquí.

Enseguida verás los pasos a seguir para crear una base de datos con phpMyAdmin. Asegúrate de consultarlos, pues te servirán tanto para conocer la plataforma, como para el desarrollo de las prácticas que debes realizar a lo largo del tema.


La finalidad de este tema es que sepas cómo acceder a la información de una base de datos para mostrársela a tus usuarios de manera legible y ordenada. Para ello debes lograr que PHP y MySQL trabajen juntos como una máquina perfectamente aceitada.

Para empezar prepara un archivo nuevo en tu editor de texto, pues primero vamos a probar la conexión con la base de datos. No te preocupes por lo que no comprendas, en su momento se explicarán todas las novedades incluidas en el código.

Este proceso se sigue para usar MySQL con PHP:

Sigue este ejemplo y ejecútalo en el servidor local:

Desde tu editor favorito crea un nuevo archivo PHP, escribe lo siguiente y guárdalo como login.php:

<?php
      // archivo para “loguearnos” con la base de datos
  $hn = 'localhost'; //o puede ser 127.0.0.1, es lo mismo :)
  $db = 'test_database'; //aqui pon el nombre de tu base de datos
  $un = 'root'; //tu usuario en caso de que sea otro
  $pw = ' '; //contraseña en caso de que la hayas configurado
?>

Los nombres de las variables usadas deben permitir recordar a qué se está refiriendo, entonces: $hn (Host Name), $db (Data Base), $un (User Name) y $pw (PassWord). En un servidor local, lo estándar es que el usuario sea root y el password no sea nada. Estos son obligatorios en un servidor externo como una medida de seguridad. Eso es todo para el archivo login.php que es bastante claro; es un archivo que generamos con todos los datos de acceso, de manera que sólo los tengamos que incluir en los archivos que lo requieren.

En un nuevo documento con nombre conecta.php escribe:

<?php
  require_once 'login.php';  //necesitamos este archivo!
  $conn = new  mysqli($hn, $un, $pw, $db); //creamos un objeto $conn
  if ($conn->connect_error) //hay errores?
mysql_fatal_error();//si los hay ejecuta esta funcion! die($conn->connect_error); //si los hay terminemos este asunto :( function mysql_fatal_error() {//mensaje de error para el usuario echo <<< _END <h3 style="color:red;">Lo sentimos pero no podemos procesar el archivo.</h3> <p>Por favor regresa a la pagina anterior.<br>Si experimentas mas errores por favor envia un correo a: <a href="mailto:admin@server.com">Soporte tecnico</a>. Gracias!</p> _END; }
?>

¿Qué es esto?

Primero requerimos el archivo login.php el cual se necesita para abrir la conexión con la base de datos. Al utilizar require_once estamos asegurándonos que el archivo se integre y se ejecute, si no es así existirá un error fatal y se detendrá la ejecución. ¿Qué error puede ser más fatal que no conectarse a la base de datos en un proyecto que usa base de datos?

Como segundo paso creamos un nuevo objeto $conn que está llamando a una nueva instancia del método mysqli y le pasamos los valores que tomamos del archivo login.php. La clase mysqli de PHP representa una conexión entre una base de datos MySQL y PHP, otorgándole varias funcionalidades.

Como tercer paso debes asegurarte de que no existan errores,  esto se logra al hacer referencia a la propiedad  connect_error ($conn->connect_error). Un cuarto paso es avisar al usuario que tenemos problemas técnicos e invitarlo a seguir navegando otra sección o a avisarnos del problema. Esto lo hacemos con una función que en este caso llamamos mysql_fatal_error().
Para probar el sistema de aviso de error, coloca mal el usuario o contraseña.

Si todo es correcto no recibirás ningún aviso y verás una bonita pantalla blanca. No tiene nada porque sólo hicimos la conexión, falta extraerla y desplegarla en la pantalla.

Con esta información ya puedes hacer una conexión con la base de datos para mostrar de manera legible una base de datos. Crea un nuevo documento (peliculas.php) en la misma ubicación que login.php y escribe lo siguiente:

<html>
      <head>
    	<title>Catalogo de Peliculas</title>
  </head>    
 <body>
	<?php
   	    require_once 'login.php'; //ya sabemos que es esto :)
		$conn = new mysqli($hn, $un, $pw, $db);
   if ($conn->connect_error){//revisamos errores
  		 die($conn->connect_error);
	   }
 	    $_query = "SELECT * FROM db_peliculas";//query de SQL
	   $result = $conn->query($_query); //objeto nuevo
         if (!$result){//revisamos errores
  	      die($conn->error);
         }	 
         $rows = $result->num_rows; //checamos los rows de informacion
         for ($j = 0 ; $j < $rows ; ++$j){//un loop, lo recuerdas?
  	     $result->data_seek($j);//buscamos la informacion del renglon seleccionando
  	     $row = $result->fetch_array(MYSQLI_ASSOC);//regresa la información foramateada   	 
		//codigo que repetimos
  	    echo 'Folio: ' . $row['id'] . '<br>';
         echo 'Nombre pelicula: ' . $row['nombre'] . '<br>';
  	    echo 'Tipo de pelicula: ' . $row['tipo_pelicula'] . '<br>';
  	    echo 'Clasificacion: ' . $row['clasificacion'] . '<br>';
  	    echo "_____________________<br><br>";
      }
     $result->close();
     $conn->close();
	?>
	</body>
 </html>

A continuación se muestra el significado de los nuevos términos y algunas acciones clave del código que acabas de ver:

$_query = "SELECT * FROM db_peliculas";

Es una petición o consulta (query) de SQL que literalmente significa: Selecciona todo (*) de la base de datos db_peliculas.

$result = $conn->query($_query);

Aquí estamos asignando el resultado de la consulta al objeto $result.

$rows = $result->num_rows;

De la información tomamos el número de filas o renglones (num_rows) y lo asignamos al objeto $rows.

$result->data_seek($j);

Buscamos la información mediante data_seek().

$row = $result->fetch_array(MYSQLI_ASSOC);

A un nuevo objeto llamado $row le asignamos el resultado de la información que tomamos mediante fetch_array(MYSQLI_ASSOC).

fetch_array(MYSQLI_ASSOC)

Devuelve una matriz de información que corresponde a la fila recuperada y se mueve hacia el próximo.

MYSQLI_ASSOC

Devuelve una matriz asociativa que representan las filas obtenidas en el conjunto de resultados. Cada llave en la matriz representa el nombre de una de las columnas del conjunto de resultados o NULL si no hay más filas en el resultado.
Por ejemplo:
nombre => Starwars, id => 1.

$row['id']

Este renglón y los otros similares, significan que estamos insertando la información que nos devuelve de esa fila. En este caso estamos inyectando la información de la columna id de la tabla db_peliculas.

Al final se cierran las conexiones. Al ejecutar este ejemplo en el browser, deberías de obtener una pantalla así:

Haz clic en el botón para acceder a la práctica.


Recuerda que debes guardar todos los ejemplos y proyectos en el folder de XAMPP correspondiente. La organización de tus archivos es una parte muy importante del flujo de trabajo, te permite localizar archivos de manera eficiente a ti y más importante, a un equipo de trabajo.

6.2 Printf, tiempo y fecha

Por el momento vamos a dejar de lado las bases de datos para continuar explorando algunas características útiles de PHP.

Printf

Hasta ahora has visto las funciones de echo y de print, que dan salida a la información en forma de texto en la pantalla del navegador. Sin embargo, existe una función más potente, printf que controla el formato de la salida y permite poner caracteres especiales de formato en una cadena de texto.

En el siguiente ejemplo se utiliza el indicador %f para mostrar el resultado de una operación:

printf("El gran total es de: $%.2f", 123.42 / 12);

$%.2f indica a PHP que requerimos conversión a un número float de dos cifras. Puedes tener tantos especificadores como quieras en una función printf, siempre y cuando pases un número igual de argumentos y siempre y cuando cada especificador esté precedido por un símbolo %.

Observa la siguiente expresión:

printf("Mi nombre es %s. Tengo %d años cumplidos, que en formato hexadecimal serian %X.", 'Tutan-Kamon', 2034, 2034);

Puedes ver que existen tres especificadores % y tres parámetros, por lo tanto no aparece ningún error. Para ver el listado de parámetros disponible y aprender un poco más acerca de esta función, haz clic aquí.

Precisión

PHP no sólo permite tener control sobre el formato, sino que también brinda control sobre la precisión del resultado. Supón que necesitas desplegar el importe del envío de un producto de una tienda virtual que estás desarrollando, al precio del producto le debes agregar un costo por manejo y envío del 22%, es decir $345.

Entonces podemos desplegar la información de la siguiente manera:

printf("El costo total es de: $%.2f", 345 + (345* 0.22) );
//regresa El costo total es de: $420.90


Observa el indicador %.2f, éste le dice a PHP que sólo utilice dos decimales en el resultado final, que es un número float. Observa que entre el indicador % y el 2 existe un punto ( . ), éste es necesario para que se ejecuten correctamente los comandos.

Haz clic en el botón para acceder a la práctica.


Sprintf

En ocasiones no requieres desplegar la información en la pantalla, sino que la necesitas enviar a una variable para utilizarla. La función sprintf te permite lograr este objetivo.

<?php   
   $retail_price = 500;//precio de lista   
  function miCalculus(){
  	global $retail_price;
  	$discount = sprintf("$%.2f", $retail_price / 2);//que buen descuento!   	echo "El precio con descuento es de " . $discount;
  }   
  miCalculus();
?>

Tiempo y fecha

Tocamos este tema en algún módulo inicial del curso y ahora vamos a explicarlo más a fondo. PHP usa por default el formato Unix para sus funciones de fecha y tiempo, para comprobarlo puedes ejecutar la función interna time();

echo time();
//la hora en que escribimos el ejemplo era 1432597753

Este tipo de salida de tiempo no es muy útil para los usuarios, ya que no podemos  procesar con claridad esa información, entonces podemos utilizar los distintos formatos que PHP nos ofrece. Si deseas conocer más sobre la función date() y sus propiedades, haz clic aquí.

La función checkDate (month,day,year); verifica la fecha acorde al calendario Gregoriano. Los parámetros son mes, día y año y se validan de acuerdo a esta tabla:

month

Requerido. Especifica los meses del 1 al 12

day

Requerido. Muestra los días del 1 al 31

year

Requerido. Especifica el año entre el 1 y el 32767

La función puede aplicarse de la siguiente manera:

<?php   
  $month = 9; // Septiembre
  $day = 31; // 31...oops! solo tiene 30 dias!
  $year = 2018; // del 2018
  if (checkdate($month, $day, $year)) echo "La fecha es valida";
     else echo "La fecha es invalida";
?>

¡Practica con esta función! Cambia el día a 5 y verás que la fecha es válida.

6.3 Manejo de archivos

Potente como es, MySQL no es la única o mejor manera de almacenar información en un servidor web. En ocasiones es más rápido y conveniente acceder directamente a los archivos en el disco duro. Enseguida verás distintas formas de hacer esto.

Creando archivos

Empecemos por crear un archivo llamado testfile.txt que no existe en el servidor local. Créalo y escribe algo de texto en él. Luego en tu editor crea el archivo writeFile.php y escribe estas líneas:

<?php   
   $fh = fopen("testfile.txt", 'w') or die("Failed to create file");
$text = <<<_END
Un poco de texto por aqui.
Otro poco de texto por aca.
Mas texto
_END;
  fwrite($fh, $text) or die("No es posible escribir el archivo!");
  fclose($fh);
  echo "El archivo 'testfile.txt' fue creado exitosamente!";
?>

¿Ves lo que ocurrió con este código? Observa lo que implica cada función:

Para empezar, fopen() sirve para abrir el archivo. Si no existe el mismo, entonces lo crea. La sintaxis de la función es la siguiente fopen(filename,mode,include_path,context). En nuestro caso particular, s+olo utilizamos filename y mode respectivamente. El modo 'w' le indica a PHP que este archivo se encuentra listo para escribir sobre él. En una variable $text escribimos un heredoc con el texto que queremos escribir en el archivo.

Por otro lado, fwrite() sirve para escribir en el archivo que ha sido abierto. Su sintaxis es fwrite(file,string,length). En nuestro caso solo usamos los dos primeros parámetros para escribir en el archivo. La tercera opción, (length, es opcional para definir la cantidad máxima de bytes que se pueden escribir. Por último en el código flcose() cierra el archivo.

Precaucion!

Si el archivo ya existe, el modo w causa que la llamada de fopen borre el contenido original incluso si no has escrito nada nuevo. Para leer el contenido de este archivo, sólo tenemos que invocar a la función fread().

<?php   
   $file = fopen("testfile.txt","r");
  fread($file,"10");
  fclose($file);
?>

La sintaxis completa de dicha función es fread(file,length). Si observas en el ejemplo pasamos el archivo que queremos acceder y le pedimos que lea 10 bytes de información. Ahora bien, para leer el archivo completo usamos filesize de esta manera: fread($file,filesize ("testfile.txt")); y finalmente se cierra el archivo al final.

Otra manera de leer el archivo y acceder a su información es utilizando fgets(), esta función toma una línea completa y la devuelve. .La sintaxis de la misma debe ser fgets(file,length). Observa el siguiente ejemplo:

<?php   
  $fh = fopen("testfile.txt", 'r') or
  die("El archivo no existe o no tienes permiso para abrirlo.");
  $line = fgets($fh);
  fclose($fh);
  echo $line;
?>

Puedes observar que el segundo parámetro es opcional. Al igual que en fread() especifica la cantidad de bytes leer, el default es de 1024.

file_get_contents()

Con file_get_contents() podemos tomar el contenido de un archivo, leer la información y pasarla a un string. Veamos este ejemplo:

<?php   
echo file_get_contents("testfile.txt");
  //debe de regresar el contenido del archivo
?>

La sintaxis que sigue esta función es:
file_get_contents(path,include_path,context,start,max_length);. Pero en nuestro ejemplo sólo utilizamos el primer parámetro, path el cual básicamente busca la ruta al archivo que vamos a leer. Los demás parámetros son opcionales y puedes consultarlos aquí.

copy()

Seguramente te puedes imaginar para que sirve esta función. ¿Alguna idea? Sirve para crear un “clon” de tu archivo de texto. Practícalo haciendo una copia de testfile.txt. Ecribe este nuevo ejemplo:

<?php   
copy('testfile.txt', 'leopardo.txt') or die("No logramos copiar el archivo!");
  echo "Se copio con exito el archivo a: 'leopardo.txt'";
?>

Si todo pasa como debe ser, ahora tienes  una copia exacta de testfile.txt en un tu servidor local.
La sintaxis básica de tal función es copy(file,to_file);. El primer parámetro es el archivo que queremos copiar y el segundo el destino y nombre donde se copiará.

Pero ten cuidado, si el archivo destino ya existe, se va a sobrescribir.

unlink()

Para borrar archivos usamos la función unlink() cuya sintaxis básica es unlink(filename,context);. El primer parámetro busca el archivo a eliminar y el segundo context, es una serie de opciones que pueden ser modificadas mediante comportamientos de flujo (stream).

Este ejemplo lo demuestra:

<?php   
  $file = "testfile.txt";
  if (!unlink($file)) {
    echo ("Error deleting $file");
 } else {
   echo ("Deleted $file");
   }
?>

Para actualizar la información de un archivo tenemos que abrirlo, colocarlo en modo de escritura, colocar el puntero del archivo en la posición donde queremos escribir nueva información y guardarlo. Algo como lo que se muestra a continuación:

<?php   
   $fh = fopen("testfile.txt", 'r+') or die("Failed to open file");
  $text = fgets($fh); //en este caso vamos a copiar y pegar
  fseek($fh, 0, SEEK_END);
  fwrite($fh, "$text") or die("Could not write to file"); //escribimos
  fclose($fh); //cerramos documento
  echo "File 'testfile.txt' successfully updated";
?>

Hasta ahora has visto en acción varias de estas funciones, así que pon especial atención a fseek(). Veamos el proceso completo de su uso:

  1. Primero abrimos el archivo testfile.txt y lo colocamos en modo de escritura, esto se hace con "r+" (Read/Write) desde el inicio del archivo y colocando  el “cursor”  al principio del documento.
  2. Le asignamos a la variable $text el nuevo texto.
  3. fseek($fh, 0, SEEK_END) mueve el cursor al final del documento.
  4. fwrite($fh, "$text") escribe el nuevo texto al final del documento.
  5. Por último, cerramos el documento.

Si todo se hizo correctamente, el documento de texto debe de tener nuevo contenido.

6.4 Carga de archivos al servidor

Este aspecto puede ser distinto en servidores reales, pues el nivel de seguridad es incrementado por obvias razones, sin embargo la técnica es la misma y sólo tendrías que ponerte de acuerdo con el servicio que tienes contratado para poder acceder a esta funcionalidad. Escribe el siguiente ejemplo, con él debes ser capaz de guardar archivos en el servidor local. Como siempre explicaremos todo pieza por pieza para que no tengas dudas:

<?php  //upload.php  
  echo  <<<_END
  <html><head><title>Carga  tu archivo!</title></head><body>
  <form  method='post' action='upload.php' enctype='multipart/form-data'>
  Selecciona tu  archivo: <input type='file' name='filename' size='10'>
  <input  type='submit' value='Upload'>
  </form>
  _END; 
  if ($_FILES) {
  $name = $_FILES['filename']['name'];
  move_uploaded_file($_FILES['filename']['tmp_name'], $name);
  echo "Uploaded image  '$name'<br><img src='$name'>";
  }
  echo  "</body></html>";
?>

Al ejecutar el programa una pantalla como ésta aparece después de cargar la imagen:

El ejemplo que viste muestra una técnica común en la programación web, en donde un programa se llama dos veces: una cuando el usuario visita la página y de nuevo cuando el usuario presiona el botón upload en la forma. El código PHP para recibir los datos de subida es bastante simple. Todos los archivos a subir son colocados en la matriz $_FILES. Por lo tanto, una comprobación rápida para ver si $_FILES contiene algo es suficiente para determinar si el usuario ha cargado un archivo. Esto se hace con la declaración if ($_FILES).

La declaración $_FILES está vacía la primera vez que el usuario entra a la página y antes de subir algún archivo, por lo que el programa ignora este bloque de código. Cuando el usuario sube un archivo, el programa se ejecuta de nuevo y descubre un elemento en el array $_FILES.

Una vez que el programa detecta que un archivo ha sido subido, el nombre del archivo es leído en el servidor, se recupera y se coloca en el nombre de la variable $. Lo que resta es mover el archivo de la ubicación temporal en el que PHP almacena el archivo cargado a una más permanente. Esto lo hacemos mediante la función move_uploaded_file y pasándole el nombre original del archivo, con el que se guarda en el directorio final. Por último, la imagen cargada se visualiza en una etiqueta img que colocamos dentro del último echo.


Para consultar una explicación más detallada, haz clic aquí.

Cierre


En el tema pudiste conocer MySQL y cómo hacer una base de datos con varios tipos de información, asimismo conociste phpMyAdmin. En el tema se mostró cómo crear un archivo para conectar PHP y la base de datos de MySQL, también ya sabes la manera de incluir archivos de conexión para evitar reescribirlos.

Entre otros aprendizajes, en el tema tuviste la oportunidad de aprender a desplegar la información de la base de datos en una página web, escribir, modificar y borrar archivos de texto y cómo funciona el sistema para subir archivos al servidor.

¡Sigue practicando! Con los conocimientos que has adquirido crea una nueva base de datos y conéctala para que despliegue su información mediante PHP y MySQL.

Checkpoint


Asegúrate de poder:

  • Crear una base de datos en MySQL con varios tipos de datos.
  • Conectar PHP con una base de datos.
  • Desplegar la información de una base de datos a través de una página web.

Referencias


  • Boronczyk, T., Naramore, E., Gerner, J., Le Scouarnec, Y. y Stolz, J. (2009). Beginning PHP 6, Apache, MySQL 6 Web Development. EE. UU.: Wiley.
  • Nixon, R. (2014). Learning PHP, MySQL & JavaScript With jQuery, CSS & HTML5. EE. UU.: O’Reilly Media.