›
›
›
  1. docs
  2. ›
  3. byrcsc/laravel-hold
1.x
Browse documentationOpenClose

Getting started

  • Introduction
  • Installation and setup
  • Quick start

Core concepts

  • Holdables and holders
  • Capacity and slots
  • Acquiring holds
  • Releasing and extending
  • Expiry
  • Hold state

Operations

  • Events and listeners
  • Scheduling expiry
  • Pruning history
  • Concurrency and databases

Reference

  • Configuration
  • Console commands
  • Database schema
  • Testing
  • Troubleshooting

Getting started

  • Introduction
  • Installation and setup
  • Quick start

Core concepts

  • Holdables and holders
  • Capacity and slots
  • Acquiring holds
  • Releasing and extending
  • Expiry
  • Hold state

Operations

  • Events and listeners
  • Scheduling expiry
  • Pruning history
  • Concurrency and databases

Reference

  • Configuration
  • Console commands
  • Database schema
  • Testing
  • Troubleshooting

byrcsc/laravel-hold · 1.x

Quick start.

Acquire, extend, release, and expire a hold on an Eloquent model.

This walkthrough reserves one Seat for one User. It assumes Laravel Hold is installed and migrated.

1. Add the traits

Add Holdable to the resource:

use ByRcsc\LaravelHold\Concerns\Holdable;

class Seat extends Model
{
    use Holdable;
}

Add HasHolds to the holder when you want to read holds from that side:

use ByRcsc\LaravelHold\Concerns\HasHolds;

class User extends Authenticatable
{
    use HasHolds;
}

A Seat has one slot by default, so only one active hold can occupy it.

2. Acquire a hold

$hold = $seat->acquireHold(
    $user,
    expiresAt: now()->addMinutes(15),
    metadata: ['reason' => 'checkout'],
);

The method returns the new hold when a slot is available:

$seat->availableSlots();      // 0
$seat->isFullyHeld();         // true
$seat->activeHoldFor($user);  // the new hold

Another holder cannot take the occupied slot:

$seat->acquireHold($otherUser); // null

Use acquireHoldOrFail() when refusal should throw NoAvailableSlotsException instead of returning null.

3. Extend the hold

use Carbon\CarbonInterval;

$hold->extend(CarbonInterval::minutes(5));

The interval is added to the current expires_at value. Extending a 15-minute hold by five minutes gives it a 20-minute window from acquisition.

Released, expired, and indefinite holds cannot be extended.

4. Release the slot

$hold->release(
    by: $supportUser,
    metadata: ['reason' => 'checkout cancelled'],
);

Release records the time, optional actor, and metadata. The hold remains in the table as history, but no longer consumes capacity:

$hold->status;                    // HoldStatus::Released
$seat->fresh()->availableSlots(); // 1

Calling release() again changes nothing.

5. Let a hold expire

$brief = $seat->acquireHold(
    $user,
    expiresAt: now()->addSeconds(2),
);

$brief->status;          // HoldStatus::Active
$seat->availableSlots(); // 0

sleep(3);

$brief->status;          // HoldStatus::Expired
$seat->availableSlots(); // 1

No command frees the slot. Availability checks compare expires_at with the current time. The optional hold:expire command records that the expiry was announced and dispatches HoldExpired.

What to read next

  • Capacity and slots to allow several active holds on one resource.
  • Acquiring holds for transactions, refusal handling, and repeat submissions.
  • Releasing and extending for complete state and metadata rules.
  • Expiry to understand lazy expiry and the optional command.
  • Concurrency and databases to see how the last slot is protected.
PreviousInstallation and setupNextHoldables and holders
View source

On this page

  1. 1. Add the traits
  2. 2. Acquire a hold
  3. 3. Extend the hold
  4. 4. Release the slot
  5. 5. Let a hold expire
  6. What to read next