PHPackages                             svandragt/silverstripe-optimisticlocking - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Validation &amp; Sanitization](/categories/validation)
4. /
5. svandragt/silverstripe-optimisticlocking

AbandonedArchivedSilverstripe-module[Validation &amp; Sanitization](/categories/validation)

svandragt/silverstripe-optimisticlocking
========================================

Prevents your site users from losing data by blocking the save process if the data has changed since it was loaded by the current user.

873PHP

Since Apr 14Pushed 10y ago1 watchersCompare

[ Source](https://github.com/svandragt/silverstripe-optimisticlocking)[ Packagist](https://packagist.org/packages/svandragt/silverstripe-optimisticlocking)[ RSS](/packages/svandragt-silverstripe-optimisticlocking/feed)WikiDiscussions master Synced yesterday

READMEChangelogDependenciesVersions (1)Used By (0)

silverstripe-optimisticlocking
==============================

[](#silverstripe-optimisticlocking)

This is a very simple module that prevents your site users from losing data. It works by blocking the save process if the data changes since it's loaded. (user1 starts editing, user 2 starts editing, user1 saves, now user2 can't overwrite user1's changes). By default, Silverstripe lets you lose data by overwriting whatever is in the database on save .

Usage:
------

[](#usage)

1. Install using composer `composer require "svandragt/silverstripe-optimisticlocking:*"`
2. Attach the OptimisticLocking class to your data objects / page types, eg. `Test` DataObject:

    `Object::add_extension("Test","OptimisticLocking");`

I keep a [list of known bugs](https://github.com/svandragt/silverstripe-optimisticlocking/issues?labels=bug&page=1&state=open).

What is Optimistic / Pessimistic locking?
-----------------------------------------

[](#what-is-optimistic--pessimistic-locking)

These are methodologies used to handle multi-user issues. How does one handle the fact that 2 people want to update the same record at the same time?

**1.Do Nothing**

- User 1 reads a record
- User 2 reads the same record
- User 1 updates that record
- User 2 updates the same record

User 2 has now over-written the changes that User 1 made. They are completely gone, as if they never happened. This is called a 'lost update' and is how SilverStripe works by default.

**2.Lock the record when it is read: Pessimistic locking**

- User 1 reads a record *and locks it* by putting an exclusive lock on the record (FOR UPDATE clause)
- User 2 attempts to read *and lock* the same record, but must now wait behind User 1
- User 1 updates the record (and, of course, commits)
- User 2 can now read the record *with the changes that User 1 made*
- User 2 updates the record complete with the changes from User 1

The lost update problem is solved. The problem with this approach is concurrency. User 1 is locking a record that they might not ever update. User 2 cannot even read the record because they want an exclusive lock when reading as well. This approach requires far too much exclusive locking, and the locks live far too long (often across user control - an *absolute* no-no). This approach is almost *never* implemented.

**3. Use Optimistic Locking.**
Optimistic locking does not use exclusive locks when reading. Instead, a check is made during the update to make sure that the record has not been changed since it was read. This module implements this.

*Thanks to [chrisrlong](http://www.dbasupport.com/forums/showthread.php?7282-What-is-Optimistic-Locking-vs.-Pessimistic-Locking&p=29149#post29149) for the original explanation.*

###  Health Score

22

—

LowBetter than 22% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity12

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity41

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

### Community

Maintainers

![](https://www.gravatar.com/avatar/a42fc2280fbcf46560c203bb7a0dc56a26ab8cf99f574b6aeb3f2cb95eaa3862?d=identicon)[svandragt](/maintainers/svandragt)

---

Top Contributors

[![svandragt](https://avatars.githubusercontent.com/u/594871?v=4)](https://github.com/svandragt "svandragt (5 commits)")

### Embed Badge

![Health badge](/badges/svandragt-silverstripe-optimisticlocking/health.svg)

```
[![Health](https://phpackages.com/badges/svandragt-silverstripe-optimisticlocking/health.svg)](https://phpackages.com/packages/svandragt-silverstripe-optimisticlocking)
```

###  Alternatives

[webmozart/assert

Assertions to validate method input/output with nice error messages.

7.6k894.0M1.2k](/packages/webmozart-assert)[bensampo/laravel-enum

Simple, extensible and powerful enumeration implementation for Laravel.

2.0k15.9M104](/packages/bensampo-laravel-enum)[swaggest/json-schema

High definition PHP structures with JSON-schema based validation

48612.5M73](/packages/swaggest-json-schema)[stevebauman/purify

An HTML Purifier / Sanitizer for Laravel

5325.6M19](/packages/stevebauman-purify)[ashallendesign/laravel-config-validator

A package for validating your Laravel app's config.

217905.3k5](/packages/ashallendesign-laravel-config-validator)[crazybooot/base64-validation

Laravel validators for base64 encoded files

1341.9M8](/packages/crazybooot-base64-validation)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
