Skip to main content

CAP.PRESCAN.INTROSPECTION_GUARD — Schema introspection guard

  • Category: safety
  • Level: 0
  • Stability: stable
  • Suites: lint

This migration's DDL sits behind a schema-introspection guard — if (! Schema::hasColumn(...)) { ... }. Measured against the framework, this is a double trap: under pretend hasColumn() returns false for a column that really exists, so the guarded block never runs, and the introspection query itself is logged — so the statement list is non-empty yet holds none of the real DDL.

The guard is good practice, not a mistake: writing a re-runnable migration this way is exactly right. The problem is only that pretend cannot see past it. Capture the migration in shadow mode, which gets a real answer from the introspection, or remove the guard where re-runnability was not actually needed.

Flagged

public function up(): void
{
// Under pretend hasColumn() is always false, so the alter is never
// captured — the run reports a clean pass over DDL it never saw.
if (! Schema::hasColumn('users', 'slug')) {
Schema::table('users', function (Blueprint $table): void {
$table->string('slug')->nullable();
});
}
}

Preferred

// The guard is good practice — keep it. Capture this migration in shadow
// mode instead, which runs against a throwaway database and gets a real
// answer from hasColumn(), so the alter inside the guard is seen.
//
// php artisan sqlens:lint --shadow
//
// Removing the guard is the other option, only where re-runnability was
// not actually needed.