PHP 7.4+ · No dependency · CLI and web
One process at a time.
Two cron runs, two workers, two requests: only one does the job. Lock a key, do the work, unlock. Plain PHP file locks by default, your own backend when you need it.
How it works
Lock. Work. Unlock.
One class to call, one interface to implement. Nothing else to learn.
1. Lock
$locker->lock('import') takes the lock, or returns false at once if another process holds it. Pass true to wait for it instead.
2. Work
Run the code that must never run twice at the same time: an import, a report, a counter, a payment.
3. Unlock
$locker->unlock('import'). Forgot it, or the script crashed? The lock is released when the Locker is destroyed and when the script ends.
Why Lock
Small enough to trust.
A lock guards your most sensitive code. It should be short enough to read in a few minutes.
No dependency
Pure PHP 7.4+, nothing else in your vendor/. No server, no extension: the default handler uses flock().
Never stuck
A file lock belongs to the process. If it dies, even killed, the system releases the lock. No stale lock to clean by hand.
Any backend
Need a lock shared by several servers? Implement LockHandlerInterface, two methods, on top of your database or Redis.
Safe keys
Keys accept letters, digits, _ and . only. A key can never become a path outside the lock folder.
Compare
Between flock() by hand and a full lock component.
Calling flock() yourself works until you forget a release. A full component brings stores and options you may never use.
fopen() + flock() | symfony/lock | michel/lock | |
|---|---|---|---|
| Backends | Files | Many stores: files, PDO, Redis, and more | Files, or your own handler |
| Release on exit | By hand | When the lock object is destroyed | When the Locker is destroyed, and at shutdown |
| Key check | None: the key is your file path | Any string | Letters, digits, _ and . |
| Expiring locks, shared locks | No | Yes | No, by design |
| Dependencies | None | Symfony component | None |
Scope
What Lock will never do
One job: exclusive locks. Everything else belongs to your handler or your application.
- add a dependency
- require a server
- retry on a timer
- expire a lock behind your back
- accept a key that is a path
Get Lock
One Composer command.
Works in scripts, cron jobs, workers and web requests. PaperORM uses it to keep its sequences unique.
$ composer require michel/lock