{"id":36318531,"url":"https://github.com/reshadman/laravel-optimistic-locking","last_synced_at":"2026-01-11T11:10:25.510Z","repository":{"id":62534951,"uuid":"135905763","full_name":"reshadman/laravel-optimistic-locking","owner":"reshadman","description":"Adds optimistic locking feature to eloquent models.","archived":false,"fork":false,"pushed_at":"2020-04-21T23:15:54.000Z","size":19,"stargazers_count":96,"open_issues_count":7,"forks_count":25,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-10-28T09:11:40.917Z","etag":null,"topics":["database","eloquent","laravel","orm"],"latest_commit_sha":null,"homepage":null,"language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/reshadman.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-06-03T13:18:41.000Z","updated_at":"2025-10-23T14:32:14.000Z","dependencies_parsed_at":"2022-11-02T15:03:54.566Z","dependency_job_id":null,"html_url":"https://github.com/reshadman/laravel-optimistic-locking","commit_stats":null,"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/reshadman/laravel-optimistic-locking","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reshadman%2Flaravel-optimistic-locking","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reshadman%2Flaravel-optimistic-locking/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reshadman%2Flaravel-optimistic-locking/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reshadman%2Flaravel-optimistic-locking/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/reshadman","download_url":"https://codeload.github.com/reshadman/laravel-optimistic-locking/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reshadman%2Flaravel-optimistic-locking/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28301742,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-11T08:21:30.231Z","status":"ssl_error","status_checked_at":"2026-01-11T08:21:26.882Z","response_time":60,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["database","eloquent","laravel","orm"],"created_at":"2026-01-11T11:10:24.888Z","updated_at":"2026-01-11T11:10:25.505Z","avatar_url":"https://github.com/reshadman.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Laravel Optimistic Locking\n![Build Status](http://img.shields.io/travis/reshadman/laravel-optimistic-locking/master.png?style=flat-square)\n\nAdds optimistic locking feature to Eloquent models.\n\n## Installation \n```bash\ncomposer require reshadman/laravel-optimistic-locking\n```\n\n\u003e This package supports Laravel 5.5.*,  5.6.*, 5.7.*, 5.8.*, and 6.* .\n\n## Usage\n\n### Basic usage\nuse the `\\Reshadman\\OptimisticLocking\\OptimisticLocking` trait\nin your model:\n\n```php\n\u003c?php\n\nclass BlogPost extends Model {\n    use OptimisticLocking;\n}\n```\n\nand add the integer `lock_version` field to the table of the model:\n```php\n\u003c?php\n\n$schema-\u003einteger('lock_version')-\u003eunsigned()-\u003enullable();\n```\n\nThen you are ready to go, if the same resource is edited by two \ndifferent processes **CONCURRENTLY** then the following exception\nwill be raised:\n\n```php\n\u003c?php\n\\Reshadman\\OptimisticLocking\\StaleModelLockingException::class;\n```\n\nYou should catch the above exception and act properly based \non your business logic.\n\n### Maintaining lock_version during business transactions\n\nYou can keep track of a lock version during a business transaction by informing your API or HTML client about the current version:\n```html\n\u003cinput type=\"hidden\" name=\"lock_version\" value=\"{{$blogPost-\u003elock_version}}\" \n```\nand in controller: \n```php\n\u003c?php\n\n// Explicitly setting the lock version\nclass PostController {\n    public function update($id)\n    {\n        $post = Post::findOrFail($id);\n        $post-\u003elock_version = request('lock_version');\n        $post-\u003esave();\n        // You can also define more implicit reusable methods in your model like Model::saveWithVersion(...$args); \n        // or just override the default Model::save(...$args); method which accepts $options\n        // Then automatically read the lock version from Request and set into the model.\n    }\n}\n```\n\nSo if two authors are editing the same content concurrently,\nyou can keep track of your **Read State**, and ask the second\nauthor to rewrite his changes.\n\n### Disabling and enabling optimistic locking\nYou can disable and enable optimistic locking for a specific \ninstance:\n\n```php\n\u003c?php\n$blogPost-\u003edisableLocking();\n$blogPost-\u003eenableLocking();\n```\n\nBy default optimistic locking is enabled when you use\n`OptimisticLocking` trait in your model, to alter the default\nbehaviour you can set the lock strictly to `false`:\n\n```php\n\u003c?php\nclass BlogPost extends \\Illuminate\\Database\\Eloquent\\Model \n{\n    use \\Reshadman\\OptimisticLocking\\OptimisticLocking;\n    \n    protected $lock = false;\n}\n```\nand then you may enable it: `$blogPost-\u003eenableLocking();`\n\n### Use a different column for tracking version\nBy default the `lock_version` column is used for tracking\nversion, you can alter that by overriding the following method\nof the trait:\n\n```php\n\u003c?php\nclass BlogPost extends \\Illuminate\\Database\\Eloquent\\Model\n{\n    use \\Reshadman\\OptimisticLocking\\OptimisticLocking;\n    \n    /**\n     * Name of the lock version column.\n     *\n     * @return string\n     */\n    protected static function lockVersionColumn()\n    {\n        return 'track_version';\n    }\n}\n```\n\n## What is optimistic locking?\nFor detailed explanation read the concurrency section of [*Patterns of Enterprise Application Architecture by Martin Fowler*](https://www.martinfowler.com/eaaCatalog/optimisticOfflineLock.html).\n\nThere are two way to approach generic concurrency race conditions:\n 1. Do not allow other processes (or users) to read and update the same\n resource (Pessimistic Locking)\n 2. Allow other processes to read the same resource concurrently, but\n do not allow further update, if one of the processes updated the resource before the others (Optimistic locking).\n\nLaravel allows Pessimistic locking as described in the documentation,\nthis package allows you to have Optimistic locking in a rails like way.\n\n### What happens during an optimistic lock?\nEvery time you perform an upsert action to your resource(model), \nthe `lock_version` counter field in the table is incremented by `1`,\nIf you read a resource and another process updates the resource\nafter you read it, the true version counter is incremented by one,\nIf the current process attempts to update the model, simply a\n`StaleModelLockingException` will be thrown, and you should\nhandle the race condition (merge, retry, ignore) based on your\nbusiness logic. That is simply via adding the following criteria\nto the update query of a **optimistically lockable model**:\n\n```php\n\u003c?php\n$query-\u003ewhere('id', $this-\u003eid)\n    -\u003ewhere('lock_version', $this-\u003elock_version)\n    -\u003eupdate($changes);\n```\n\nIf the resource has been updated before your update attempt, then the above will simply\nupdate **no** records and it means that the model has been updated before\ncurrent attempt or it has been deleted.\n\n### Why don't we use `updated_at` for tracking changes?\nBecause they may remain the same during two concurrent updates.\n\n## Running tests\nClone the repo, perform a composer install and run:\n\n```vendor/bin/phpunit```\n\n## License\n\nThe MIT License (MIT). Please see [License File](LICENSE.md) for more information.\nense (MIT). Please see License File for more information.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freshadman%2Flaravel-optimistic-locking","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Freshadman%2Flaravel-optimistic-locking","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freshadman%2Flaravel-optimistic-locking/lists"}