Convert SQL to Laravel migrations
This SQL to Laravel migration converter reads CREATE TABLE statements and writes the equivalent Laravel migration using the schema builder. It is the fastest way to bring a legacy database, a schema designed in a GUI tool, or a mysqldump --no-data file under Laravel's migration system, so the schema can be versioned and recreated with php artisan migrate.
Example
Input:
CREATE TABLE posts (id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,user_id BIGINT UNSIGNED NOT NULL,slug VARCHAR(191) UNIQUE,body TEXT NULL,price DECIMAL(8,2) DEFAULT 0.00,is_published TINYINT(1) NOT NULL DEFAULT 0,status ENUM('draft','live') DEFAULT 'draft',created_at TIMESTAMP NULL,updated_at TIMESTAMP NULL,FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,INDEX idx_slug (slug));Output inside the generated up() method:
Schema::create('posts', function (Blueprint $table) {$table->id();$table->foreignId('user_id')->constrained()->cascadeOnDelete();$table->string('slug', 191)->unique();$table->text('body')->nullable();$table->decimal('price', 8, 2)->default(0.00);$table->boolean('is_published')->default(false);$table->enum('status', ['draft', 'live'])->default('draft');$table->timestamps();$table->index('slug', 'idx_slug');});Each table becomes its own anonymous migration class with a matching down() method that calls Schema::dropIfExists. The header comment suggests the file name, such as create_posts_table.php.
What gets converted
- Primary keys: an auto-increment
idbecomes$table->id(); anINTorSERIALid becomesincrements('id'). Composite primary keys become$table->primary([...]). - Foreign keys: integer columns with a
FOREIGN KEYbecomeforeignId()->constrained(). The short form is used when the name follows Laravel's convention (user_idtousers.id); otherwise the table and column are passed explicitly.ON DELETE/ON UPDATECASCADE,SET NULLandRESTRICTmap tocascadeOnDelete(),nullOnDelete(),restrictOnDelete()and their update versions. - Types:
VARCHAR(n)tostring(length kept unless it is 255),TEXTvariants,DECIMAL(p,s),FLOAT,DOUBLE,DATE,DATETIME,TIMESTAMP,TIMESTAMPTZ,JSON,JSONB,UUID,ENUM,BLOBandINET.TINYINT(1)becomesboolean, andUNSIGNEDintegers use theunsigned...methods. - Modifiers:
NULLaddsnullable(),UNIQUEaddsunique(),DEFAULTaddsdefault(),DEFAULT CURRENT_TIMESTAMPorNOW()addsuseCurrent(), and column comments are kept. - Laravel conventions:
created_atplusupdated_atcollapse intotimestamps(), anddeleted_atbecomessoftDeletes(). - Indexes:
INDEX,UNIQUEandFULLTEXTkeys becomeindex(),unique()andfullText(), with the original index name preserved.
Limitations
Only CREATE TABLE is converted. ALTER TABLE, views, triggers and stored procedures are skipped, and a paste with no CREATE TABLE at all produces an error. Unknown types fall back to string, so check columns like GEOMETRY or MONEY by hand. Table options such as ENGINE, CHARSET and COLLATE are not carried over, because Laravel takes them from config/database.php.
Nullability follows what the SQL states explicitly. A column that is nullable only by default, with neither NULL nor NOT NULL, is generated without nullable(), so add it where you need it. Also order your files so referenced tables are created first; migrations run in file-name order, and a foreign key to a missing table fails.
Privacy
Your schema is parsed and converted in the browser, so table and column names are never uploaded. Check the SQL first with the SQL validator, tidy it with the SQL formatter, or build a model and migration from sample data with JSON to Laravel model.