flock în PHP

Blochează un fișier ca două scripturi să nu îl modifice în același timp.

Sintaxă
flock($stream, int $operation, &$would_block = null): bool

Ce face flock

Când doi vizitatori rulează același script în același moment, ambii pot scrie în același fișier și îl pot strica. flock pune o blocare: LOCK_EX (exclusivă, pentru scriere), LOCK_SH (partajată, pentru citire) și LOCK_UN (eliberare).

Implicit, flock așteaptă până se eliberează fișierul. Cu LOCK_EX | LOCK_NB nu așteaptă, ci returnează imediat false dacă fișierul este deja blocat. Blocarea este doar o înțelegere între scripturi: un program care nu folosește flock poate scrie oricum.

Parametri

Parametru Descriere
$stream Resursa returnată de fopen.
$operation LOCK_SH, LOCK_EX sau LOCK_UN, opțional cu | LOCK_NB.
$would_block Opțional. Devine 1 dacă blocarea a eșuat pentru că altcineva ține fișierul.

Ce returnează

true dacă blocarea a reușit, altfel false.

Exemple

Exemplul 1: Contor de vizite sigur

Modul "c+" deschide fișierul fără să îl golească. Citirea, calculul și scrierea se fac cât timp fișierul este blocat.

<?php
function vizita(string $fisier): int
{
    $f = fopen($fisier, "c+");
    flock($f, LOCK_EX);

    $numar = (int) stream_get_contents($f) + 1;
    ftruncate($f, 0);
    rewind($f);
    fwrite($f, (string) $numar);

    flock($f, LOCK_UN);
    fclose($f);
    return $numar;
}

vizita("vizite.txt");
vizita("vizite.txt");
echo "Vizite: " . vizita("vizite.txt");

Rezultat

Vizite: 3

Exemplul 2: Un singur script odată (de exemplu un cron)

Simulăm al doilea script deschizând încă o dată același fișier. Cu LOCK_NB, a doua încercare eșuează imediat.

<?php
$primul = fopen("import.lock", "c");
$alDoilea = fopen("import.lock", "c");

var_dump(flock($primul, LOCK_EX | LOCK_NB));

if (!flock($alDoilea, LOCK_EX | LOCK_NB)) {
    echo "Importul rulează deja, ies.";
}

Rezultat

bool(true)
Importul rulează deja, ies.

Greșeli frecvente

  • Deschizi fișierul cu "w" și abia apoi îl blochezi. "w" l-a golit deja, înainte de blocare. Folosește "c" sau "c+".
  • Folosești flock pe fișiere de pe un disc de rețea (NFS). Acolo blocarea poate să nu funcționeze.

Comenzi înrudite

  • fopen / fclose: Deschide un fișier pentru citire sau scriere și returnează o resursă; fclose îl închide.
  • fwrite / fputs: Scrie un text într-un fișier deschis cu fopen. fputs este același lucru, cu alt nume.
  • file_put_contents: Scrie un text într-un fișier. Creează fișierul dacă nu există.