PHPackages                             chr15k/laravel-schema-audit - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Database &amp; ORM](/categories/database)
4. /
5. chr15k/laravel-schema-audit

ActiveLibrary[Database &amp; ORM](/categories/database)

chr15k/laravel-schema-audit
===========================

Performs static analysis of your Laravel migrations to detect schema inconsistencies before they ship.

0.1.0(today)10MITPHPPHP ^8.2CI passing

Since Aug 8Pushed todayCompare

[ Source](https://github.com/chr15k/laravel-schema-audit)[ Packagist](https://packagist.org/packages/chr15k/laravel-schema-audit)[ RSS](/packages/chr15k-laravel-schema-audit/feed)WikiDiscussions main Synced today

READMEChangelog (3)Dependencies (11)Versions (2)Used By (0)

  [![Schema Audit header image](art/header.jpeg)](art/header.jpeg)

 [![GitHub Workflow Status (master)](https://camo.githubusercontent.com/f4adf22b18d5139a05d6e4697143a763951a4fe4abbf3bdafcd3a3f89ec072b2/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f63687231356b2f6c61726176656c2d736368656d612d61756469742f6d61696e2e796d6c)](https://github.com/chr15k/laravel-schema-audit/actions) [![Total Downloads](https://camo.githubusercontent.com/18c1752375e32890e6eb2166fe083a287b6dd10756d38e91d9cdb5d87020302c/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f63687231356b2f6c61726176656c2d736368656d612d6175646974)](https://packagist.org/packages/chr15k/laravel-schema-audit) [![Latest Version](https://camo.githubusercontent.com/917ea80a1a6603e4a0a18fe87ceec763c7912731094c9c45475a489490fcc2b5/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f63687231356b2f6c61726176656c2d736368656d612d6175646974)](https://packagist.org/packages/chr15k/laravel-schema-audit) [![License](https://camo.githubusercontent.com/d629347731d317e7bb37fadd6248c24d8cb134efa22fcdb1fd41422f5bf3ce4a/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f63687231356b2f6c61726176656c2d736368656d612d6175646974)](https://packagist.org/packages/chr15k/laravel-schema-audit)

---

Laravel Schema Audit
====================

[](#laravel-schema-audit)

**Catch schema problems before production**

Laravel Schema Audit statically reconstructs your database schema from its migration history and catches structural issues before they reach production.

No database connection. No migration execution. Just fast, CI-friendly analysis that detects duplicate and redundant indexes, invalid foreign keys, mismatched types, invalid references, missing primary keys, and more.

Built for Laravel and designed to work with real-world migration code, including common conventions and conditional schema logic.

---

Requirements
------------

[](#requirements)

- PHP 8.2+
- Laravel 11, 12, or 13

---

Installation
------------

[](#installation)

```
composer require chr15k/laravel-schema-audit --dev
```

Optionally publish the config file:

```
php artisan vendor:publish --tag=schema-audit-config
```

---

Usage
-----

[](#usage)

```
php artisan schema:audit
```

By default this reads `database/migrations` and prints a styled report. The command exits with a non-zero status when findings are present, making it suitable for CI.

```
# scan a different migration directory
php artisan schema:audit --path=/path/to/migrations

# machine-readable output for CI and automation
php artisan schema:audit --json

# inspect the reconstructed schema without running rules
php artisan schema:audit --schema-only
```

Important

Schema Audit treats all provided migration paths as one database schema. Run separate audits for applications or connections with independent databases.

---

What gets checked
-----------------

[](#what-gets-checked)

RuleWhat it flags`UnindexedForeignKeyRule`A foreign key with no covering index. Driver-aware based on whether the target database automatically indexes foreign key columns.`DuplicateIndexRule`The same index (same columns, same uniqueness) declared more than once.`DuplicateForeignKeyRule`The same foreign key (same column, same referenced table) declared more than once.`RedundantIndexRule`A single-column index already covered by a composite index's leading column.`DanglingForeignKeyRule`A foreign key referencing a table that doesn't exist anywhere in the schema — a typo, or a table renamed/dropped without updating the reference.`MismatchedForeignKeyRule`A foreign key whose column type doesn't match the referenced table's primary key type (e.g. `foreignId()` pointing at a plain `increments()` primary key).`MissingPrimaryKeyRule`A table with no identifiable primary key — no `id()`/`increments()`-style column and no explicit `primary()` call.`InvalidReferencedKeyRule`A foreign key referencing a column with no primary or unique key on the parent table.Note

Rules run against the schema reconstructed from your migration history. For ordinary migrations, findings are concrete. Where runtime conditionals affect schema changes, affected findings are marked conditional because the resulting schema cannot be determined statically with certainty.

---

Enforce your own schema policies
--------------------------------

[](#enforce-your-own-schema-policies)

Built-in rules catch common database problems. Custom rules let your team enforce **application-specific schema standards in CI**.

For example, you might want to prevent developers from adding expensive column types to high-traffic tables:

```
final readonly class NoTextColumnsOnHighTrafficTablesRule extends Rule
{
    public function handle(AuditContext $context, Closure $next): AuditContext
    {
        $findings = [];

        foreach ($context->schema->tables() as $table) {
            if (! in_array($table->name, ['orders', 'events', 'sessions'], true)) {
                continue;
            }

            foreach ($table->columns() as $column) {
                if ($column->method === ColumnMethod::Text) {
                    $findings[] = $this->makeFinding(
                        table: $table->name,
                        columns: $column->name,
                        message: "Avoid TEXT columns on high-traffic tables.",
                        location: $column->location,
                        guard: $column->guard,
                    );
                }
            }
        }

        return $next($context->withFindings($findings));
    }
}
```

Register it alongside the built-in rules:

```
'rules' => [
    Rules\UnindexedForeignKeyRule::class,
    Rules\DuplicateIndexRule::class,
    App\SchemaRules\NoTextColumnsOnHighTrafficTablesRule::class,
],
```

This turns Schema Audit into more than a collection of database checks: **your team can codify its own schema rules and make them part of the CI pipeline.**

See [`GUIDE.md`](GUIDE.md#writing-custom-rules) for writing custom rules and advanced usage.

---

Configuration
-------------

[](#configuration)

```
// config/schema-audit.php
use Chr15k\SchemaAudit\Rules;

return [
    'paths' => [
        database_path('migrations'),
    ],
    'driver' => env('DB_CONNECTION', 'mysql'),
    'rules' => [
        Rules\UnindexedForeignKeyRule::class,
        Rules\DuplicateIndexRule::class,
        Rules\DuplicateForeignKeyRule::class,
        Rules\RedundantIndexRule::class,
        Rules\DanglingForeignKeyRule::class,
        Rules\MissingPrimaryKeyRule::class,
        Rules\MismatchedForeignKeyRule::class,
        Rules\InvalidReferencedKeyRule::class,
    ],
    'report_conditional_findings' => true,
];
```

Note

`paths` — migration directories to analyze. Use `--path` to override for a single run.

`driver` — target database driver. Some rules are driver-specific, such as whether foreign keys automatically create indexes.

`report_conditional_findings` — report findings affected by conditional schema logic. Set to `false` to suppress them.

`rules` — enable, disable, or replace audit rules.

---

Documentation
-------------

[](#documentation)

See the [Guide](GUIDE.md) for:

- supported schema operations
- static value resolution
- conditional migrations
- limitations and unsupported operations
- multiple database connections
- writing custom rules

---

Limitations
-----------

[](#limitations)

Schema Audit uses static analysis rather than executing migrations. It supports Laravel's Schema Builder and common Laravel conventions, but runtime-generated schema changes and database-specific SQL cannot always be reconstructed.

Conditional schema changes are handled conservatively and affected findings are marked **conditional**.

See the [Guide](GUIDE.md) for supported operations, conditional migrations, static value resolution, and unsupported cases.

###  Health Score

37

—

LowBetter than 81% of packages

Maintenance100

Actively maintained with recent releases

Popularity2

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity35

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

0d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/c817e814df42c78ac76505c9394a786946a0d9517b64984eca34b6f04010df95?d=identicon)[chr15k](/maintainers/chr15k)

---

Top Contributors

[![chr15k](https://avatars.githubusercontent.com/u/67823070?v=4)](https://github.com/chr15k "chr15k (162 commits)")

---

Tags

laravelschemastatic analysismigrationperformancemysqlindexoptimizationchr15k

###  Code Quality

TestsPest

Static AnalysisPHPStan, Rector

Code StyleLaravel Pint

Type Coverage Yes

### Embed Badge

![Health badge](/badges/chr15k-laravel-schema-audit/health.svg)

```
[![Health](https://phpackages.com/badges/chr15k-laravel-schema-audit/health.svg)](https://phpackages.com/packages/chr15k-laravel-schema-audit)
```

###  Alternatives

[spatie/laravel-medialibrary

Associate files with Eloquent models

6.2k45.4M688](/packages/spatie-laravel-medialibrary)[psalm/plugin-laravel

Psalm plugin for Laravel

3345.4M354](/packages/psalm-plugin-laravel)[laravel/sail

Docker files for running a basic Laravel application.

1.9k212.4M1.4k](/packages/laravel-sail)[laravel/ai

The official AI SDK for Laravel.

1.1k4.6M286](/packages/laravel-ai)[laravel/mcp

Rapidly build MCP servers for your Laravel applications.

79227.1M206](/packages/laravel-mcp)[laravel/surveyor

Static analysis tool for Laravel applications.

89157.7k16](/packages/laravel-surveyor)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
