PHP code example of heyosseus / difflock

1. Go to this page and download the library: Download heyosseus/difflock 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/ */

    

heyosseus / difflock example snippets


Schema::table('users', function (Blueprint $table) {
    $table->string('status');            // fails on a populated table
    $table->dropColumn('legacy_token');  // no down() brings the data back
    $table->renameColumn('name', 'full_name');  // breaks the release still running
});

// config/difflock.php

// 1. Exclude tables entirely — they appear in no diff and reach no file.
'ignore' => ['tables' => ['oauth_*', 'personal_access_tokens']],

// 2. Or keep the tables and drop the only two fields that carry free text.
'snapshot' => ['defaults' => false, 'comments' => false],

RiskLevel::Safe      // nothing here can lose data or break a running application
RiskLevel::Low       // reversible, unlikely to be felt
RiskLevel::Medium    // reversible, capable of noticeable impact on a busy table
RiskLevel::High      // can break the running application, or fail partway through
RiskLevel::Critical  // destroys data or structure no down() brings back

return [
    'enabled' => env('DIFFLOCK_ENABLED', true),

    'connection' => env('DIFFLOCK_CONNECTION'),

    'baseline' => env('DIFFLOCK_BASELINE', database_path('difflock/schema.json')),

    'risk' => [
        'fail_on' => env('DIFFLOCK_FAIL_ON', 'critical'),
    ],

    'protection' => [
        'enabled' => env('DIFFLOCK_PROTECTION_ENABLED', true),
        'block_on' => env('DIFFLOCK_BLOCK_ON', 'critical'),
    ],

    'thresholds' => [
        'medium_table_rows' => env('DIFFLOCK_MEDIUM_TABLE_ROWS', 100_000),
        'large_table_rows' => env('DIFFLOCK_LARGE_TABLE_ROWS', 1_000_000),
    ],

    'migrations' => [
        'paths' => [],
    ],

    'rules' => [ /* the nine built-ins */ ],

    'ignore' => [
        'rules' => [],       // 'add-index', 'drop-*'
        'tables' => [],      // 'telescope_*'
        'migrations' => [],  // '2019_*'
    ],
];

use Difflock\Contracts\MigrationRule;
use Difflock\Migration\MigrationContext;
use Difflock\Migration\Subject;
use Difflock\Risk\RiskLevel;

final class NoUuidPrimaryKeysRule implements MigrationRule
{
    public function identifier(): string
    {
        return 'no-uuid-primary-keys';
    }

    public function analyze(MigrationContext $context): array
    {
        $findings = [];

        foreach ($context->operations('uuid') as $operation) {
            if (! $operation->hasModifier('primary')) {
                continue;
            }

            $findings[] = $context->finding(
                rule: $this->identifier(),
                risk: RiskLevel::Medium,
                message: 'UUID primary key on '.$context->tableName(),
                explanation: 'Random primary keys scatter inserts across the index.',
                suggestion: 'Use an auto-incrementing key, or a ULID.',
                subject: $operation->stringArgument(0),
                subjectType: Subject::Column,
                operation: $operation,
            );
        }

        return $findings;
    }
}

// A service provider's boot()
use Difflock\Facades\Difflock;

Difflock::rule(NoUuidPrimaryKeysRule::class);

// config/difflock.php
'rules' => [
    // …
    NoUuidPrimaryKeysRule::class,
],

$context->migrationName();     // '2026_08_10_120000_remove_legacy_token'
$context->tableName();         // 'users', or null if it was not a literal
$context->liveTable();         // the table as it exists now, or null
$context->rows();              // roughly how many rows, or null if unknown
$context->reversible();        // whether down() has a body
$context->operations('index'); // the blueprint chains starting with index()
$context->database->thresholds;
$context->database->available; // false when there was no database to ask

use Difflock\Database\FixedTableStatistics;

$statistics = new FixedTableStatistics(['orders' => 8_421_392]);

use Difflock\Facades\Difflock;

$schema  = Difflock::inspect();          // the live schema
$diff    = Difflock::diff('a', 'b');     // two connections compared
$drift   = Difflock::drift();            // live vs recorded baseline
$report  = Difflock::analyze();          // the whole migration report
$findings = Difflock::lint();            // just the findings
$decision = Difflock::guard();           // should the pending migrations run?

use Difflock\Contracts\MigrationAnalyzer;
use Difflock\Contracts\SchemaDiffer;

public function __construct(
    private MigrationAnalyzer $analyzer,
    private SchemaDiffer $differ,
) {}

if (config('features.phone')) {          // may or may not run
    Schema::table(...);
}

foreach ($this->tenantTables() as $t) {  // table names unknown
    Schema::table($t, ...);
}

DB::statement('ALTER TABLE ...');        // not read at all
bash
php artisan vendor:publish --tag=difflock-config
bash
php artisan difflock:diff --save     # record the baseline
php artisan difflock:diff            # compare the live schema against it
bash
php artisan difflock:diff --from=staging --to=production
bash
php artisan difflock:lint            # pending migrations
php artisan difflock:lint --all      # every migration file
php artisan difflock:lint --accept   # record what it found as accepted
php artisan difflock:lint --path=database/migrations/legacy
bash
php artisan difflock:migrate
bash
php artisan difflock:check --ci
yaml
name: Difflock

on:
  pull_request:

jobs:
  schema:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v5

      - uses: shivammathur/setup-php@v2
        with:
          php-version: '8.3'

      - run: composer install --no-interaction --prefer-dist

      - run: php artisan difflock:check --ci
yaml
difflock:
  image: php:8.3-cli
  script:
    - composer install --no-interaction --prefer-dist
    - php artisan difflock:check --ci
jsonc
// .mcp.json — Claude Code, Cursor, Laravel Boost, anything speaking MCP
{
  "mcpServers": {
    "difflock": {
      "command": "php",
      "args": ["-d", "display_errors=stderr", "artisan", "difflock:mcp"]
    }
  }
}
bash
php artisan difflock:explain 2026_08_11_120000_drop_legacy_token