Lecciones de PHP - Lección 2 - Trabajo con archivos: apertura, escritura, lectura.
En la lección anterior creamos la estructura para nuestro libro de visitas, blog o chat. Ahora solo queda añadir funcionalidad. En esta lección escribiremos nuestras entradas en archivos y mostraremos las entradas desde los archivos.
PHP tiene muchas funciones para trabajar con archivos; revisaremos algunas de ellas. Lo más probable es que tu sitio web almacene datos en una base de datos (de eso estoy seguro), y no en archivos, así que solo veremos algunas funciones para que comprendas el concepto. Trabajaremos con bases de datos más adelante.
Si no tienes los archivos que hicimos en la lección anterior, vuelve atrás y descárgalos.
Vamos al formulario de agregar entrada:
/index.php?admin=1
Desde este formulario añadiremos nuestras entradas. Para procesarlas, necesitamos comprobar en la página index.php (a donde se envían los datos del formulario) si hay valores en la variable $_POST. Esto se comprueba fácilmente así:
if($_POST){ }
¿Verdad que es sencillo? Ahora dentro de las llaves colocamos el procesamiento del array $_POST. No escribiremos el código directamente dentro de las llaves, lo moveremos a nuestra clase, y el procesamiento se llamará a través de un método del objeto. En el archivo index.php llamamos al método:
if($_POST){ $obj->write($_POST); }
Y en el archivo simpleCMS.php implementamos el método write():
public function write($p) { // método para escribir un mensaje }
¿Por qué hacemos esto? Para reducir el código en index.php. El archivo index.php solo debe usarse para control, mientras que el procesamiento de arrays y la salida de datos debe hacerse desde otro archivo, como el de nuestra clase simpleCMS. Esta separación mejora la eficiencia del código. Si otra persona ve nuestro código, entenderá rápidamente dónde está todo. Y a ti también te resultará más fácil comprender el código cuando esté bien organizado.
Comencemos con algo simple: imprimamos el array $_POST enviado desde el formulario. Para ello, escribe este código:
public function write($p) { // método para escribir un mensaje print_r($p); }
Como ves, usamos la variable local $p, aunque el método write() recibe la variable superglobal como parámetro. No accedemos directamente a la superglobal porque en otros casos podríamos querer escribir en el blog sin usar un formulario, por ejemplo desde un archivo XML. Usar una variable local permite hacer este método más genérico y reutilizable.
Entonces, llenamos el formulario y lo enviamos. Yo obtuve estos datos:
Array ( [title] => Iván [bodytext] => ¡Hola, Mundo! )
Si tú lo llenaste de otra forma, el array será diferente. Mostramos el array para saber qué claves podemos usar. En nuestro caso, son $p['title'] y $p['bodytext']. Ahora que sabemos qué datos tenemos, solo falta escribirlos en un archivo.
Escritura de archivos en PHP
Antes de escribir algo en un archivo, es necesario "abrirlo para escritura". Esto significa vincular el archivo a una variable de PHP. Todo el trabajo con archivos en PHP se hace a través de variables del tipo resource. Ahora te mostraré lo que eso significa:
public function write($p) { // método para escribir un mensaje $message = fopen("messages/file.txt","w"); print_r($message); }
Para esto creé un archivo llamado file.txt en la carpeta messages. Ahora, si llenamos el formulario y lo enviamos, obtendremos:
Resource id #4
Resource es el tipo de variable $message, y 4 es su ID entre otras variables de tipo resource. Ahora, si realizamos acciones sobre la variable $message, estas se reflejarán automáticamente en el archivo. Escribiremos en el archivo línea por línea para luego leer también línea por línea:
public function write($p) { // método para escribir un mensaje $message = fopen("messages/file.txt","w"); fputs ($message, $p['title']. "\r\n"); fputs ($message, $p['bodytext']); }
Los caracteres \r\n entre comillas dobles (puede que no funcionen con comillas simples) indican salto de línea. El archivo file.txt tendrá este contenido:
Iván
¡Hola, Mundo!
Después de todas las acciones con el archivo, debemos liberar la variable para que no ocupe memoria RAM:
public function write($p) { // método para escribir un mensaje $message = fopen("messages/file.txt","w"); // abrimos el archivo fputs ($message, $p['title']. "\r\n"); fputs ($message, $p['bodytext']); fclose ($message); //cerramos el archivo }
Seguramente notaste que cada vez que escribimos el archivo, se sobrescribe. Esto depende del segundo parámetro de la función fopen. También podemos añadir al final o abrir solo para lectura. Por ejemplo:
$message = fopen("messages/file.txt","r"); // abrimos el archivo solo para lectura
- r – abrir el archivo solo para lectura.
- r+ – abrir el archivo para lectura y escritura.
- w – crea un archivo nuevo vacío. Si ya existe, lo sobrescribe.
- w+ – como r+, pero elimina el contenido si el archivo existe.
- a – abre un archivo existente para añadir contenido al final.
- a+ – abre para lectura y escritura, añade al final sin borrar el contenido.
Como se menciona arriba, si abrimos un archivo con el parámetro w, se crea un nuevo archivo con el nombre del primer parámetro. Vamos a usar la función time() para nombrar los archivos según la hora actual.
La función time() devuelve el número de segundos desde el 1 de enero de 1970.
Debes obtener lo siguiente:
public function write($p) { // método para escribir un mensaje $message = fopen('messages/'.time(),"w"); // abrimos el archivo fputs ($message, $p['title']. "\r\n"); fputs ($message, $p['bodytext']. "\r\n"); fputs ($message, time()); fclose ($message); //cerramos el archivo }
De esta forma, cada segundo la función time() devolverá un número mayor, y los nombres de archivo aumentarán. Puedes probar agregando nuevas entradas y verás nuevos archivos en la carpeta messages. Ahora solo falta leer los archivos y mostrar las entradas.
Lectura de archivos en PHP
Para leer un archivo, primero hay que abrirlo en modo lectura. Usaremos el parámetro r en la función fopen(). Todos los archivos están en la carpeta messages, así que los leeremos usando un bucle while (mientras haya archivos).
Leeremos los archivos de la carpeta usando la función opendir(), que abre la carpeta para lectura:
if (is_dir('messages')) { // comprobamos si la carpeta existe if ($dh = opendir('messages')) { // abrimos la carpeta while (($file = readdir($dh)) !== false) { // mientras haya archivos, los leemos // ejecutamos las operaciones necesarias } closedir($dh); //cerramos la carpeta } }
Obtenemos los nombres de los archivos con readdir(), y se almacenan en la variable $file. Al final del bucle cerramos la carpeta para liberar memoria.
Ahora que podemos leer archivos, mejoraremos el método display_public():
public function display_public() { // método para mostrar mensajes $content = ''; if (is_dir('messages')) { // comprobamos si la carpeta existe if ($dh = opendir('messages')) { // abrimos la carpeta while (($file = readdir($dh)) !== false) { // mientras haya archivos, los leemos if(substr($file, -4) == '.txt'){ // solo tomamos archivos .txt $filename = 'messages/' . $file; // nombre completo del archivo $message = fopen($filename, 'r'); // abrimos el archivo $title = fgets($message); // leemos la primera línea $body = fgets($message); // leemos la segunda línea $time = fgets($message); // leemos la tercera línea print '<div class="post">'; // div envolvente print '<span class="time">' . date('d-m-Y', $time) . '</span><h2>' . $title . '</h2>'; // mostramos fecha y título print '<p>' . $body . '</p>'; // mostramos el mensaje print '</div>'; // cierre del div fclose($message); // cerramos el archivo } } closedir($dh); //cerramos la carpeta } } $content .= '<p><a href="/index.php?admin=1">Agregar mensaje</a></p>'; return $content; }
He comentado cada línea. Si algo no queda claro, escribe en los comentarios y lo explicaré.
No creo que en la práctica necesites leer archivos línea por línea, pero para entender los principios del trabajo con funciones PHP, archivos y carpetas, estas lecciones son muy útiles.
A continuación el código fuente del sitio intermedio.