exolnet/laravel-sqlite-fluent-drop-foreign
Provides a workaround for dropping foreign keys on SQLite when using Laravel’s fluent schema builder, so migrations can remove foreign key constraints cleanly despite SQLite’s limited ALTER TABLE support.
This package patches Laravel's SQLite schema grammar so dropForeign() becomes a fluent, no-op-safe operation instead of throwing RuntimeException: This database driver does not support dropping foreign keys. You reach for it when a single migration has to run against both SQLite (local dev, CI, in-memory tests) and MySQL/Postgres (production).
Requirements as of v1.12.0: PHP 8.3+ and Laravel 12+. PHP 8.2 and Laravel 11 support were removed in this release — check composer.json before upgrading.
composer require exolnet/laravel-sqlite-fluent-drop-foreign
The service provider is auto-discovered; there is no publish step and no config file. Look first at:
Schema calls are intercepted.tests/ directory — the fixtures show which dropForeign() signatures (array, string, explicit index name) are covered.database/migrations/ for any migration that currently branches on DB::getDriverName().First use case: delete the driver check from a migration and let it run unchanged.
Schema::table('posts', function (Blueprint $table) {
$table->dropForeign(['user_id']); // works on sqlite now
});
Write migrations driver-agnostically. The whole point is to remove the if (DB::getDriverName() === 'sqlite') { ... } else { ... } forks. Keep one code path and let the package intercept on SQLite while MySQL/Postgres use the native grammar.
Make down() symmetric. Because the package emulates the drop by rebuilding the table, the reverse migration ($table->foreign('user_id')->references('id')->on('users')) is the real test of correctness. Always exercise migrate:rollback and migrate:refresh locally before merging.
Test suite on SQLite, production on MySQL. This is the highest-value integration: keep phpunit.xml pointed at sqlite/:memory: so RefreshDatabase exercises every dropForeign() in your migration history on every run. Failures surface at PR time instead of during a deploy.
CI matrix after upgrading to v1.12. Drop the php: 8.2 and laravel: 11.* rows from your GitHub Actions matrix in the same commit as the composer.json bump, or the first green build will be followed by a wall of resolver failures.
Use it for the "legacy cleanup" migration. Dropping a foreign key that a previous team added and nobody remembers is exactly the scenario the package exists for — you can write the cleanup without special-casing SQLite and without leaving a permanent driver branch in the repo.
Pair with Schema::withoutForeignKeyConstraints() when the migration does more than one structural change, so the rebuild doesn't trip FK enforcement mid-flight.
"exolnet/laravel-sqlite-fluent-drop-foreign": "^1.11" and don't let a composer update drift you forward. If you're on Laravel 12 but PHP 8.2, you must upgrade PHP first — the constraint will otherwise fail resolution with a confusing message.Blueprint (custom indexes, triggers, WITHOUT ROWID, collations, partial index predicates) may not survive. Diff sqlite_master before and after on any table with hand-written DDL.dropForeign(['user_id']) resolves the conventional posts_user_id_foreign index name. Custom names must be passed explicitly: dropForeign('my_custom_fk_name'). A "constraint not found" error on SQLite but not MySQL is almost always a naming mismatch.DB::enableQueryLog() around the migration, or DB::listen(), and inspect the CREATE TABLE ... AS/rename sequence. Inspect the result directly with SELECT sql FROM sqlite_master WHERE type='table' AND name='posts'; — the remaining FK clauses are right there.DB::transaction() can produce confusing failures. Prefer letting Artisan manage the transaction boundary.dropForeign on SQLite works without the package; if it does, removing this dependency is a one-line composer remove plus deleting any explicit service provider registration.How can I help you explore Laravel packages today?