PHP code example of mueller-schmitz / laravel-model-integrity

1. Go to this page and download the library: Download mueller-schmitz/laravel-model-integrity library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

mueller-schmitz / laravel-model-integrity example snippets


use Illuminate\Database\Eloquent\Model;
use MuellerSchmitz\ModelIntegrity\Concerns\HasIntegrity;

class Invoice extends Model
{
    use HasIntegrity;

    protected string $integrityMode = 'versioned';    // 'versioned' | 'immutable'
    protected string $integrityDeletes = 'record';    // 'forbid' | 'record'
    protected array $integrityExcept = ['updated_at']; // not part of snapshots
    protected array $integrityRelations = ['tags'];   // related keys are part of every snapshot
    protected int $integritySchemaVersion = 1;        // bump when the snapshot structure changes
}

$invoice->withIntegrityReason('Customer complaint')
    ->withIntegrityContext(['ticket' => 'SUP-123'])
    ->update(['total' => '90.00']);

use MuellerSchmitz\ModelIntegrity\ModelIntegrity;

ModelIntegrity::actingAs($user, fn () => $invoice->update([...]));
ModelIntegrity::actingAs('system'); // a label instead of a model

use MuellerSchmitz\ModelIntegrity\Casts\AsIntegrityFile;
use MuellerSchmitz\ModelIntegrity\Facades\IntegrityFiles;

// Migration: $table->char('pdf', 64)->nullable();

class Invoice extends Model
{
    use HasIntegrity;

    protected function casts(): array
    {
        return ['pdf' => AsIntegrityFile::class];
    }
}

$invoice->update(['pdf' => IntegrityFiles::store($request->file('pdf'))]);

$invoice->pdf->sha256;      // the column holds the hash, which is part of the snapshot
$invoice->pdf->readStream();
$invoice->pdf->contents();
IntegrityFiles::find($sha256);

class Order extends Model
{
    use HasIntegrity;

    protected array $integrityPersonal = ['shipping_name', 'shipping_address'];
    protected array $integrityAnonymized = ['shipping_name' => ''];   // allowed after shredding, besides null

    public function integritySubject(): ?Model   // default: the model itself
    {
        return $this->customer;
    }
}

use MuellerSchmitz\ModelIntegrity\Facades\IntegritySubjects;

IntegritySubjects::shred($customer, 'Erasure request #42');   // or: php artisan model-integrity:shred "App\Models\Customer" 42 --reason="..."
IntegritySubjects::isShredded($customer);

$version->revealedSnapshot()->snapshot;   // personal attributes decrypted, null once shredded
$version->revealedSnapshot()->shredded;   // the attributes whose key was shredded

DB::transaction(function () use ($post, $tagIds) {
    $post->tags()->sync($tagIds);
    $post->recordRelation('tags');
});

$invoice->integrityVersions()->get(); // query builder, oldest first
$invoice->history();                  // collection, see Verification

use MuellerSchmitz\ModelIntegrity\Facades\IntegrityChecker;

$result = IntegrityChecker::checkModel($invoice);

$result->passes();
$result->fails();
$result->errors();            // Collection<IntegrityError>
$result->checkedVersions();
$result->lastValidVersion();  // the chain is intact up to this version

IntegrityChecker::getHistory($invoice);                // Collection<Version>, oldest first
IntegrityChecker::getHistory($invoice, verify: true);  // each version with ->isValid()
IntegrityChecker::versionAt($invoice, '2026-03-01');   // version current at that moment
IntegrityChecker::checkType(Invoice::class);           // all invoices, including deleted ones
IntegrityChecker::checkChain();                        // the global chain over all models
IntegrityChecker::checkAll();                          // global chain, anchors and every recorded model
IntegrityChecker::checkAnchors();                      // the anchors against the versions and their proofs
IntegrityChecker::checkFiles();                        // hashes the content of every stored file

// routes/console.php
use Illuminate\Support\Facades\Schedule;

Schedule::command('model-integrity:verify')->dailyAt('03:00')->emailOutputOnFailure('[email protected]');

// routes/console.php
Schedule::command('model-integrity:anchor')->hourly()->withoutOverlapping();
Schedule::command('model-integrity:anchor-upgrade')->hourly()->withoutOverlapping(); // OpenTimestamps

// config/model-integrity.php
'anchors' => [
    'drivers' => ['disk'],
    'disk' => [
        'disk' => env('MODEL_INTEGRITY_ANCHOR_DISK', 'local'),
        'path' => 'integrity-anchors',
    ],
],

// config/model-integrity.php
'anchors' => [
    'drivers' => ['disk', 'opentimestamps'],
    'opentimestamps' => [
        'calendars' => [/* four public calendars by default */],
        'min_calendars' => 2,
        'timeout' => 10,
        'esplora_url' => env('MODEL_INTEGRITY_ESPLORA_URL', 'https://blockstream.info/api'),
    ],
    'max_delay_hours' => 72,
    'since' => env('MODEL_INTEGRITY_ANCHORS_SINCE'), // e.g. "2026-10-01" when upgrading
],

// config/model-integrity.php
'anchors' => [
    'drivers' => ['disk', 'opentimestamps', 'rfc3161'],
    'rfc3161' => [
        'url' => env('MODEL_INTEGRITY_TSA_URL'),            // e.g. https://freetsa.org/tsr
        'ca_file' => env('MODEL_INTEGRITY_TSA_CA_FILE'),    // PEM file with the TSA's CA certificates
        'intermediates_file' => null,
        'policy' => null,                                   // 

use MuellerSchmitz\ModelIntegrity\Anchoring\AnchorManager;

app(AnchorManager::class)->extend('archive', fn () => new ArchiveAnchor);
bash
composer model-integrity:install
php artisan migrate
bash
php artisan model-integrity:grants --user=app
php artisan model-integrity:grants --user=app --host=10.0.0.% --all-tables  # MySQL/MariaDB
bash
php artisan model-integrity:snapshot --model="App\Models\Invoice" --reason="Added reference column"
php artisan model-integrity:snapshot --all
bash
php artisan model-integrity:anchor-export 42 ./audit
ots verify ./audit/00000000000000001234-<digest>.json.ots
bash
php artisan model-integrity:export storage/audit/2026                     # everything
php artisan model-integrity:export storage/audit/2026 --from=2026-01-01 --to=2026-12-31
php artisan model-integrity:export storage/audit/invoices --model="App\Models\Invoice"
php artisan model-integrity:export storage/audit/2026 --files --no-reveal --fetch-dtd