Search by

cosmira / sandbox

tabuna

Draft and publish database-backed Laravel configuration safely.

Package info

github.com/cosmira/sandbox

pkg:composer/cosmira/sandbox

Statistics

Installs: 5

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

0.1.0 2026-09-14 15:56 UTC

This package is not auto-updated.

Last update: 2026-09-16 09:55:07 UTC


README

Tests Code Coverage Markdown

Database-backed drafts for Laravel configuration screens.

Edit configuration through Eloquent shadow tables, then publish, discard, or save the draft. One user owns the editing session. Active data remains available while the owner works on pricing rules, category trees, feature flags, or other shared configuration.

Requirements

  • PHP 8.2 or later.
  • Laravel 12 or 13, with a PHP version supported by that Laravel release.
  • SQLite, PostgreSQL, or MySQL.
  • An active table and a matching draft table for each registered model or table.

See upgrading from 0.1.0 when updating an existing integration.

Installation

composer require cosmira/sandbox:^0.1
php artisan vendor:publish --tag=sandbox-migrations
php artisan migrate

Publish migrations only for a new installation. For an existing shared status schema, follow the installation guide.

Create matching shadow tables in your application's migrations. For example, categories uses categories_sb by default. Sandbox does not create those tables.

Quick start

Add HasSandbox to each configuration model:

use Cosmira\Sandbox\HasSandbox;
use Illuminate\Database\Eloquent\Model;

class Category extends Model
{
    use HasSandbox;

    public $timestamps = false;

    protected $table = 'categories';
}

Register models in an application service provider, in dependency order:

use App\Models\Category;
use Cosmira\Sandbox\Facades\Sandbox;

Sandbox::models(Category::class);

Protect configuration routes with authentication and the sandbox middleware:

use App\Http\Controllers\CategoryController;
use Illuminate\Support\Facades\Route;

Route::middleware(['auth', 'sandbox'])->group(function (): void {
    Route::resource('categories', CategoryController::class);
});

Controllers keep using normal Eloquent queries. The first mutating request copies active configuration into the draft and locks it for the current user. The application's own authorization rules still determine who may edit.

Finish the session explicitly:

use Cosmira\Sandbox\Facades\Sandbox;

Sandbox::me()->commit(note: 'Publish configuration');
// Or discard changes:
Sandbox::me()->rollback(note: 'Discard draft');
// Or keep the draft for later:
Sandbox::me()->save(note: 'Continue tomorrow');

Lifecycle

Operation Result
open() on a free sandbox Copy active data into the draft and lock it
open() on a saved draft Resume editing without resetting changes
commit() Publish the draft and release the lock
rollback() Replace the draft with active data and release the lock
save() Keep the draft and pause editing

The owner reads and writes a locked draft. Other users read active data and cannot modify the locked configuration. Authenticated users can read a saved draft; guests always read active data. Host permissions apply to every operation.

An edit includes opening, locking, and writes in one transaction. Exceptions and HTTP responses with status 400 or higher roll it back. Completed lifecycle events run after commit, so a listener failure cannot undo published data.

Documentation

Development

composer install
composer test
composer test:coverage
composer test:mutation
composer test:types
composer test:rector
npx --yes markdownlint-cli2@0.23.2

CI runs the PHP/Laravel matrix on Ubuntu and dedicated Windows concurrency checks, plus PostgreSQL and MySQL contracts. Separate workflows check Composer metadata, PHPStan, Rector, Soda, coverage, mutations, spelling, ShellCheck, and Markdown. Pint commits formatting fixes on pushes and checks pull requests. Statement coverage must reach 80%; Infection requires 96% MSI and covered MSI.

soda.php combines Soda's standard rules with multiline PHPDoc checks for all methods, properties, and constants in src, regardless of visibility. Promoted properties can be documented with a matching constructor @param tag. CI installs Soda separately so Sandbox keeps supporting PHP 8.2. With a local Soda checkout, run:

php /path/to/soda/soda quality src --config=soda.php

Limitations

  • One global configuration session per application.
  • Model table selection belongs to the application context; concurrent coroutine runtimes sharing that context are unsupported.
  • Hydrated models retain their selected table after a context ends. Do not carry draft models across authorization boundaries.
  • Raw SQL and DB::table() calls do not switch tables automatically.
  • Oracle native integration is unverified. A custom backend must preserve the enclosing transaction and enforce the same lifecycle contract.

License

MIT.