Skip to content

feat: add Model withLockedRow()#10388

Open
memleakd wants to merge 3 commits into
codeigniter4:4.8from
memleakd:feat/model-with-locked-row
Open

feat: add Model withLockedRow()#10388
memleakd wants to merge 3 commits into
codeigniter4:4.8from
memleakd:feat/model-with-locked-row

Conversation

@memleakd

@memleakd memleakd commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Description

This PR proposes adding withLockedRow() to CodeIgniter\Model.

It is a small helper for cases where we need to reload a single row inside a transaction, lock it for update, and then run some code with that locked row.

$result = $accountModel->withLockedRow($id, static function (object $account, $model): bool {
    $account->balance -= 100;

    return $model->save($account);
});

This gives users a clear path for single-row mutations that need a pessimistic lock, without having to remember to manually wrap lockForUpdate() in a transaction each time. It does not add new lock behavior; it only scopes the existing transaction and lock APIs together.

The method uses the existing transaction() helper and Query Builder lockForUpdate(), so it follows the same transaction and driver-specific locking behavior.

A few details:

  • if the row is not found, the callback is not called and null is returned
  • if the transaction cannot start or fails without an exception, false is returned
  • if the callback throws, the transaction is rolled back and the exception is rethrown
  • existing Model query constraints, like where() and withDeleted(), are applied
  • Model find callbacks are not run for the locked reload, so they cannot skip the actual database read

This does not add new lock modes or special driver handling. Unsupported lock combinations still throw the same exceptions as lockForUpdate().

Checklist:

  • Securely signed commits
  • Component(s) with PHPDoc blocks, only if necessary or adds value (without duplication)
  • Unit testing, with >80% coverage
  • User guide updated
  • Conforms to style guide

- add withLockedRow() for running a callback with a row locked for update
- bypass find callbacks for the locked reload while preserving normal callback behavior inside the callback
- clean up model state when the locked lookup fails
- document transaction, constraint, and driver-lock behavior
- add focused unit and live model coverage

Signed-off-by: memleakd <121398829+memleakd@users.noreply.github.com>
@github-actions github-actions Bot added the 4.8 PRs that target the `4.8` branch. label Jul 8, 2026
memleakd added 2 commits July 8, 2026 03:16
Signed-off-by: memleakd <121398829+memleakd@users.noreply.github.com>
Signed-off-by: memleakd <121398829+memleakd@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

4.8 PRs that target the `4.8` branch.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant