PHP (08) Archivos (12) Bloqueo de archivos

En una aplicación web es bastante normal que haya varios usuarios trabajando a la vez, de hecho no es raro pensar que puedan estar intentando atacar al mismo archivo a la vez varios de ellos, pudiendo crear conflictos.

Para evitar este tipo de problemas se puede utilizar la función flock:

flock (handle, operation [, &wouldblock] )

Aquí handle hace referencia al archivo que será bloqueado y operation puede tomar los siguientes valores:

  • LOCK_SH: Para adquirir un bloqueo compartido (lector)
  • LOCK_EX: Para adquirir un bloqueo exclusivo (escritor)
  • LOCK_UN: Para liberar un bloqueo, sea del tipo que sea

El tercer elemento es opcional se establece a TRUE si el bloqueo esta teniendo lugar y a FALSE si no es así.

La función flock normalmente bloquea (no retorna), hasta que se pueda asegurar un bloqueo. Si no deseamos esperar y dejar de este modo nuestro código bloqueado, estableceremos con OR las constante LOCK_NB a la condición como; LOCK_EX | LOCK_NB. Esto hará que la función retorne de inmediato, y si no consiguió un bloqueo, puede esperar un segundo (con la función sleep(1)) y reintentarlo de nuevo hasta en 15 ocasiones.

Hasta aquí todo es teoría pero podemos verlo en el siguiente script:

<?php
 $handle = fopen("archivo/file.txt", "w");
 $text = "Éste\nes\nel\ntexto del bloqueo.";
 //se comprueba que el archivo no este bloqueado
 if (flock($handle, LOCK_EX | LOCK_NB)) {
  echo "<p>;Se bloqueó el archivo. </p>;";
 //comprueba que se pueda escribir en el archivo
 if (fwrite($handle, $text) == FALSE) {
  echo "<p>;No se puede escribir en file.txt. </p>;";
 }
 else {
  echo "<p>;Se escribió en data.txt.</p>;";
 }
 //desbloquea el archivo para otro usuario
 flock($handle, LOCK_UN);
  echo "<p>;Se desbloqueó el archivo. </p>;";
 }
 //desde aquí solo lee el archivo para comprobarlo
 $handle = fopen("archivo/file.txt", "r");
 if($handle){
  echo '<p>;El archivo se ha abierto correctamente</p>;<p>;';
  while ($char = fgetc($handle)){
   if ($char == "\n"){
    $char='</p>;<p>;';
   }
   echo $char;
  }
  fclose($handle);
 }else{
  echo '<p>;ERROR AL ABRIR EL ARCHIVO</p>;';
 }
?>;

Lo cual nos da como resultado la entrada al archivo y su modificación mientras lo bloquea para que otro usuario no pueda modificarlo al mismo tiempo.

Se bloqueó el archivo.

Se escribió en file.txt.

Se desbloqueó el archivo.

El archivo se ha abierto correctamente

Éste

es

el

texto del bloqueo.