yriveiro/php-fslock
A lightweight PHP library for managing file locks. It wraps flock() to acquire shared or exclusive locks, supports blocking and non-blocking modes, and provides simple lock release, helping coordinate concurrent processes and prevent race conditions.
flock() into a small lock object with acquire/release semantics. The real product decision it informs is whether a wrapper earns a dependency slot at all. PHP's flock() is one function call; a package must justify itself with ergonomics (named locks, blocking vs. non-blocking, timeouts, cleanup, destructor-based release). Evaluate the source against that bar, not its star count. The 3.0.0 release trims the API (removal of destroy()) and adds lock-path configuration — it is converging on a smaller, sharper surface, which strengthens the "buy/borrow rather than build" case slightly, but does not change the underlying math.flock is an OS-level advisory lock scoped to a machine and filesystem. It directly supports decisions like "do we need Redis/DynamoDB locking, or is one host enough for now?" Choosing this package is an explicit bet that the workload runs on one machine — which is a legitimate near-term call for cron jobs, report generators, and nightly imports.withoutOverlapping() middleware — fewer moving parts./tmp, or place them alongside app storage for easier cleanup and inspection. It also creates a new failure mode to decide on deliberately — do not point this at a network mount (NFS/EFS/SMB) under the assumption that it makes the lock cross-host. flock on network filesystems is unreliable; the parameter relocates the file, it does not distribute the lock.Consider it when all of the following hold:
flock semantics are unreliable on NFS and other network mounts; assume local disk only. Configure the path for isolation and hygiene, not for sharing.Look elsewhere — or skip the dependency entirely — when:
flock gives no cross-machine mutual exclusion. You will get false confidence: the lock "works" in staging and silently fails to protect anything in production. Use Redis (SET NX PX), a database advisory lock, or Laravel's cache-based locks with a shared store.withoutOverlapping() or a Redis lock is better supported and already observable.flock releases on process exit, which is good, but there is no lease/expiry concept. Long-running hung processes holding a lock are a real operational risk.destroy() outright with no deprecation path and no shim. Any code holding a lock object and calling destroy() will fatal after upgrade. This is a small library being versioned like a library with real users; budget a grep-and-fix pass every time.flock() is often the easier approval path, and now also the easier-to-upgrade path given the PHP 7 floor.If already adopted: treat 3.0.0 as a migration, not a patch. Find every destroy() call site, drop it, and confirm lock release is still covered by the destructor/release path. Then set the new lock path explicitly rather than inheriting a default — a deliberate, documented directory is easier to operate and to back up or clean than an implicit one.
To executives: We have a class of operational bugs — the same nightly job running twice, duplicated customer emails, double-generated invoices — caused by processes overlapping. This is a small, MIT-licensed utility that prevents that on a single server for essentially zero cost and no infrastructure change. It is not a platform investment and it is not a long-term commitment; it is a cheap guardrail that buys us correctness now. Two things to flag. First, it only protects a single machine, so the moment we scale to multiple app servers or containers, we must replace it with a distributed lock — a known, bounded piece of work worth putting on the roadmap before an incident finds it for us. Second, it now requires PHP 7 across the hosts that use it, and its new major version changed its API, so there is a small migration cost if we already depend on it. The project also shipped its first release in years, which is mildly reassuring on maintenance but confirms that version bumps can arrive whenever the maintainer chooses — so we pin it.
To engineering: It's a thin, readable wrapper over flock(). Low risk, low surface area, no transitive dependency weight. Changes in 3.0.0 to account for: PHP 7.x minimum; explicit return types (no behavioral change); a new constructor parameter for the lock storage directory; and destroy() removed with no deprecation shim — grep for it before upgrading, and rely on release/destructor for cleanup instead of reusing a destroyed instance. Three caveats to accept explicitly: (1) it is maintained only sporadically, so treat it as vendored code — read it, pin it, and be prepared to fork or replace it; (2) flock is host-local and unreliable on network filesystems, so this is a single-node solution only — the new path parameter does not make it cross-host, and pointing it at a shared mount is a trap, not a feature; (3) there is no observability or TTL/lease concept, so hung processes can hold a lock indefinitely. Prefer the framework's built-in withoutOverlapping() if a shared cache or database already exists; use this only where a shared store doesn't. Wrap it in a small service so the eventual swap to Redis or a DB lock is a one-file change, set the lock directory explicitly in config, and add a log line on lock acquisition failure so we can see contention in production.
How can I help you explore Laravel packages today?