axn/laravel-pk-int-to-bigint
Safely convert Laravel integer primary keys to bigint with this package's migration helpers and Artisan commands, updating existing ID columns and related foreign keys so your database is ready for large datasets without breaking references.
This package solves one specific problem: an existing Laravel schema that still uses increments()/integer (32-bit) primary and foreign keys and needs to move to 64-bit bigIncrements()/bigInteger before you hit the 2.1B (signed) / 4.29B (unsigned) ceiling. It is a one-shot migration aid, not a runtime dependency, so install it as a dev dependency.
composer require --dev axn/laravel-pk-int-to-bigint
Where to look first:
php artisan list | grep -i bigint — confirm the exact command signature the package registers; it exposes an artisan command that inspects your schema and generates a conversion migration rather than altering tables directly.config/pk-int-to-bigint.php (publish it if present) — this is where table/column exclusions, connection name, and output path are typically configured.database/migrations/ — this is the real artifact you will review, edit, and ship.First use case: an application with users.id as int unsigned auto_increment that is approaching ~1B rows, plus a dozen tables with user_id foreign keys typed int unsigned. Run the generator, review the migration it produces, and apply it on a staging copy of production before it ever touches a live database. Typical starting command:
php artisan vendor:publish --tag=pk-int-to-bigint-config # if the package ships one
php artisan pk-int-to-bigint:generate # verify name via artisan list
Treat the generated migration as a draft, not a finished product. The package's job is to find int PKs and the FK columns that reference them; your job is to validate the list against reality. A good workflow:
information_schema (SHOW CREATE TABLE for each table) — confirm unsigned/signed, defaults, and that every FK column is included.down() if the package generates a stub — you will almost never roll this back in production, but you want a safe no-op or a documented irreversible step rather than a broken reverse.Order-of-operations for foreign keys. Altering a PK that other tables reference requires either dropping FKs first and re-adding them after, or wrapping the whole migration in SET FOREIGN_KEY_CHECKS=0; ... SET FOREIGN_KEY_CHECKS=1;. If the generated migration doesn't do this, add it — the classic failure mode here is errno: 150 halfway through.
Large tables need online DDL. The generated migration is plain ALTER TABLE ... MODIFY, which locks or rebuilds the table on MySQL. For any table over a few million rows, do not run this through php artisan migrate. Use the generated SQL as the source of truth and apply it via pt-online-schema-change or gh-ost, table by table, in FK dependency order. Keep the artisan migration in the repo for fresh installs and small environments.
Handle the tables the scanner can't see. Package migrations, pivot tables, and polymorphic *_type/*_id columns often use unsignedInteger without a real FK constraint, so a schema-introspection-based tool won't always flag them. Grep the codebase and database/migrations for ->integer(, ->unsignedInteger(, and increments( after the package runs and reconcile the list manually.
Model and API layer. PHP integers are 64-bit on any modern platform, so $model->id keeps working. The things that break are elsewhere: json_encode of IDs into JS (JavaScript Number is only safe to 2^53 — cast large IDs to string in API resources), any int column in a cache/session/queue payload that assumes 32 bits, and external integrations with a typed int field.
Third-party overrides. If you rely on packages that publish their own migrations with increments(), you'll need to either fork the migration, add a follow-up migration in your app that alters those columns, or wait for an upstream release. Keep a list of these — the package won't know about them unless they've already run.
int unsigned (max 4.29B) and int signed (max 2.1B) convert to different bigint variants. An unsignedInteger FK pointing at a bigInteger PK (signed) will fail on the FK constraint. Normalize everything to unsignedBigInteger if your PKs are unsigned.composer.json constraint vs. your framework version is the first thing to verify — the last release date being recent doesn't mean it supports your pinned Laravel. ->change() also requires doctrine/dbal on older Laravel versions; if the generated migration uses change(), add the dependency or rewrite as raw ALTER.down() method. Most tools in this space generate an empty or naive down(). If it tries to reverse a bigint back to int on a table with values above 2^31, it will silently truncate or error. Replace it with a comment explaining the migration is intentionally irreversible.AUTO_INCREMENT counter is preserved by MODIFY COLUMN, so you don't need to reset it — but verify on staging with SHOW TABLE STATUS if you've previously done manual inserts.ALTER COLUMN TYPE. integer → bigint is a table rewrite and the sequence must be altered too (ALTER SEQUENCE ... AS bigint). If the package targets MySQL primarily, double-check its Postgres output or write that migration yourself.jobs, failed_jobs, migrations, sessions) are often fine to skip, and excluding them shortens migration time and reduces blast radius.ALTER fails, run the statements one at a time in a scratch database. The error code (150 = FK, 1832 = FK column type mismatch, 1215 = cannot add FK) tells you exactly which pair is inconsistent.bigIncrements from day one — otherwise new environments will recreate the int schema and you'll be running this tool again. For a 19-star package, budget time to read the source: it's small, and you'll want to know exactly what SQL it emits before pointing it at production.How can I help you explore Laravel packages today?