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
flockpe 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ă.