elnur/database-migrations
A Laravel package for working with database migrations, offering a simple way to organize and run schema changes in PHP applications. It aims to streamline common migration tasks while staying lightweight and easy to integrate.
Install and register. composer require elnur/database-migrations. If the package doesn't support package auto-discovery (it's old and low-traffic — check composer.json for extra.laravel.providers), add the service provider to config/app.php under providers. Run php artisan list and look for the package's command (commonly something like db:migrate, migrate:sql, or sql:migrate) — this is your entry point for everything else.
Look at these three things first, in order:
config/ file — it defines the migration directory, the tracking table name, and the DB connection used. Publish it (php artisan vendor:publish --provider="Elnur\...\...ServiceProvider") so you can change paths without touching vendor code.src/ — read how it discovers files, sorts them, and whether it splits on ; or executes whole files. That single detail dictates everything about how you write your SQL.First use case. The natural entry point is anything Laravel's Schema builder handles poorly: a CREATE VIEW, a Postgres trigger function, a MySQL stored procedure, or a bulk data backfill. Drop a timestamped .sql file into the configured directory, run the package's migrate command, and confirm the row appears in the tracking table. Once that works, you understand the whole package.
One file per logical change, timestamp-prefixed. Follow the same YYYY_MM_DD_HHMMSS_description.sql convention as native Laravel migrations. The package almost certainly sorts lexically, so consistent zero-padded timestamps matter more than with PHP migrations because you have no class name to fall back on.
Keep native migrations and SQL migrations in separate lanes. The value of this package is that it tracks state in its own table, independent of migrations. Use native migrations for schema you want the Schema DSL for (and want migrate:rollback/migrate:fresh to handle), and reserve SQL files for objects the DSL can't express. Document the split in README/CONTRIBUTING so the next developer doesn't guess.
Write idempotent SQL where the dialect allows it. CREATE TABLE IF NOT EXISTS, CREATE OR REPLACE VIEW, DROP TRIGGER IF EXISTS. Because the package's failure semantics are simple (an error aborts the run), idempotency lets you re-run after a partial failure without hand-editing the tracking table.
Structure for data backfills. Wrap large UPDATE/INSERT ... SELECT in explicit BEGIN; ... COMMIT; only if your file is executed as a single unit and your dialect supports transactional DDL. Otherwise chunk by primary key inside the SQL and make the file re-runnable.
Environment-gated execution in deploy pipelines. Run the package's migrate command in your deploy script before the app comes up, gated on the same --force/--env guard you use for php artisan migrate. Since there's no dependents and only a single star, treat it as your own code: pin the version in composer.json and review the diff on upgrade.
Rollback by paired files. If the package supports a down convention (e.g. foo.down.sql), use it. If it doesn't — and likely it doesn't — keep a sibling *.down.sql file in a database/sql/rollback directory and run it manually. Don't pretend you have automatic rollback.
Multi-connection setups. Point the config at a specific connection rather than relying on the default, especially in apps with a read/write split. Migrations must run against the writer.
;, which silently breaks on Postgres $$ ... $$ function bodies, MySQL DELIMITER blocks, semicolons inside string literals, and -- comments. Before writing any procedure or trigger, verify how the package feeds statements to PDO — if it splits naively, keep such objects in a separate file and run them by hand, or patch the runner.BEGIN/COMMIT — but be aware the package may already wrap, and nesting will warn.CREATE produces a syntax error that's easy to misread as a permissions problem.-v to the artisan command, tail the DB's error log or storage/logs/laravel.log, and query the tracking table directly (select * from <tracking_table> order by id desc limit 5) to confirm what actually recorded. If a file ran but wasn't recorded, it will re-run next deploy — verify the insert path before assuming success.migrate:fresh in tests. RefreshDatabase doesn't know about this package. Either run the SQL migrations in your test bootstrap explicitly, or (better) keep test schema entirely in native migrations and use SQL files only for objects that tests don't touch.--pretend flag — those are the features you'd get for granted from migrate. Subclass, register your own command, and keep the vendor directory pristine.How can I help you explore Laravel packages today?