W3docs

flock()

La fonction flock() en PHP permet de mettre en place un mécanisme simple de verrouillage de fichiers pour éviter les conflits d'accès concurrent.

Qu'est-ce que la fonction flock() ?

La fonction flock() effectue un verrouillage de fichier en PHP. Un verrou permet à un processus d'indiquer aux autres : « Je travaille avec ce fichier — attendez votre tour. » Sans cela, deux scripts s'exécutant simultanément peuvent entrelacer leurs écritures et corrompre un fichier. C'est une condition de course classique, et flock() est l'outil le plus simple que PHP vous offre pour la prévenir.

Cette page couvre ce que fait la fonction, ses types de verrous, un exemple complet et fonctionnel que vous pouvez exécuter, les pièges courants, et sa place parmi les autres fonctions PHP de gestion de fichiers.

Une note sur le verrouillage « consultatif »

Sur les systèmes de type Unix, flock() est consultatif : le verrou n'est respecté que par les processus qui appellent également flock() sur le même fichier. Un programme qui ignore le verrouillage peut toujours lire ou écraser le fichier librement. Le verrouillage ne vous protège donc que si tous les scripts qui accèdent au fichier coopèrent. Sous Windows, le verrouillage est obligatoire (appliqué par le système d'exploitation), ce qui entraîne un comportement légèrement différent selon les plateformes — ne vous fiez pas à un verrouillage obligatoire dans du code portable.

Syntaxe

flock($stream, $operation, &$would_block = null): bool
ParamètreDescription
$streamUn pointeur de fichier retourné par fopen().
$operationL'une des constantes de verrou ci-dessous, éventuellement combinée avec LOCK_NB via un OU bit à bit.
$would_blockFacultatif. Défini à 1 si le verrou aurait bloqué (seulement pertinent avec LOCK_NB). Passé par référence.

La fonction retourne true en cas de succès ou false en cas d'échec.

Types de verrous

ConstanteSignification
LOCK_SHVerrou partagé (lecteur). Plusieurs processus peuvent détenir un verrou partagé simultanément, mais aucun ne peut en détenir un exclusif pendant ce temps. À utiliser lors des lectures.
LOCK_EXVerrou exclusif (écrivain). Un seul processus peut le détenir ; tous les autres — lecteurs et écrivains — attendent. À utiliser lors des écritures.
LOCK_UNLibère le verrou actuellement détenu sur le flux.
LOCK_NBModificateur non bloquant. Combinez-le avec LOCK_SH ou LOCK_EX (ex. `LOCK_EX

Par défaut, flock() bloque : si un autre processus détient un verrou exclusif, votre appel attend que le verrou soit libéré. Ajoutez LOCK_NB si vous préférez échouer rapidement.

Comment utiliser la fonction flock()

Le schéma est toujours le même en quatre étapes :

  1. Ouvrir le fichier avec fopen() en utilisant un mode adapté à ce que vous ferez ('r+', 'c', 'a', …).
  2. Acquérir le verrou avec flock($file, LOCK_EX) (ou LOCK_SH pour lire).
  3. Lire ou écrire dans le fichier.
  4. Libérer avec flock($file, LOCK_UN) et fermer avec fclose().

Un exemple complet et exécutable

Ce script ouvre un fichier compteur, le verrouille exclusivement, incrémente le nombre stocké et le réécrit — le type de lecture-modification-écriture qui doit être verrouillé pour être sûr en cas d'accès concurrent :

<?php

$filename = 'counter.txt';

// 'c' opens for read/write, creating the file if missing,
// and does NOT truncate it (unlike 'w').
$file = fopen($filename, 'c+');

if ($file === false) {
    exit("Could not open file.\n");
}

if (flock($file, LOCK_EX)) {        // block until we hold the lock
    $current = (int) stream_get_contents($file);
    $current++;

    rewind($file);                  // back to the start
    ftruncate($file, 0);            // clear old contents
    fwrite($file, (string) $current);
    fflush($file);                  // push to disk before unlocking

    flock($file, LOCK_UN);          // release the lock
    echo "Counter is now: $current\n";
} else {
    echo "Could not acquire lock.\n";
}

fclose($file);

En l'exécutant trois fois, on obtient Counter is now: 1, puis 2, puis 3. Parce que la séquence lecture-incrémentation-écriture se déroule sous LOCK_EX, deux processus ne peuvent jamais lire la même valeur et écrire tous les deux 2.

Échouer rapidement avec un verrou non bloquant

Quand vous ne souhaitez pas attendre — par exemple une tâche cron qui devrait passer son tour si une précédente est encore en cours — combinez LOCK_EX avec LOCK_NB :

<?php

$file = fopen('job.lock', 'c');

if (flock($file, LOCK_EX | LOCK_NB)) {
    echo "Got the lock, doing work...\n";
    // ... long-running task ...
    flock($file, LOCK_UN);
} else {
    echo "Another instance is already running. Exiting.\n";
}

fclose($file);

Pièges courants

  • Les verrous sont attachés au descripteur de fichier ouvert, pas au chemin. Appeler fopen() deux fois sur le même fichier donne deux descripteurs indépendants, et un verrou sur l'un ne bloque pas l'autre dans le même processus.
  • Utilisez 'c'/'c+', et non 'w', lors du verrouillage. Le mode 'w' tronque le fichier à l'instant où vous l'ouvrez — avant d'acquérir le verrou — ce qui annule l'intérêt du verrouillage. Tronquez explicitement avec ftruncate() après avoir obtenu le verrou.
  • flock() ne fonctionne pas de manière fiable sur NFS ou certains systèmes de fichiers réseau ou FAT. Pour la coordination entre plusieurs serveurs, utilisez un vrai service de verrouillage (un verrou de ligne de base de données, Redis, etc.) à la place.
  • fclose() libère tout verrou restant, mais déverrouillez explicitement avec LOCK_UN pour que le fichier soit à nouveau disponible dès que vous avez terminé.

Conclusion

flock() est l'outil intégré de PHP pour coordonner l'accès concurrent à un fichier. Utilisez LOCK_EX autour des écritures, LOCK_SH autour des lectures, et LOCK_NB quand vous préférez échouer plutôt qu'attendre. N'oubliez pas que le verrouillage sous Unix est consultatif — il ne vous protège que si tous les scripts qui accèdent au fichier y participent. Pour un travail de fichier de plus haut niveau, consultez fwrite(), fread() et file_put_contents().

Pratique

Pratique
Quelle est la fonction de flock() en PHP ?
Quelle est la fonction de flock() en PHP ?
Was this page helpful?