Schema::create() passes a Blueprint to a closure; each method call adds a column, and the driver's grammar turns it into DDL. This is MySQL's products table the Laravel 2,157 way:
Schema::create('products', function (Blueprint $table) {
$table->id();
$table->string('sku', 20)->unique();
$table->string('title', 200);
$table->foreignId('category_id')->constrained();
$table->decimal('price', 8, 2);
$table->unsignedInteger('stock')->default(0);
$table->json('attributes')->nullable();
$table->timestamps();
});Columns are NOT NULL unless you chain nullable(). string, char, decimal, enum, json and dateTime map one to one onto MySQL's types; SHOW CREATE TABLE showed these differences:
| Blueprint method | MySQL type created | MySQL choice |
|---|---|---|
| id() | bigint unsigned auto-increment primary key | INT UNSIGNED |
| foreignId('category_id') | bigint unsigned | SMALLINT UNSIGNED |
| string('sku', 20) | varchar(20) COLLATE utf8mb4_unicode_ci | VARCHAR(20), server collation |
| timestamps() | two timestamp NULL columns | created_at DATETIME only |
Keys are BIGINT because foreignId() must match id() (Foreign Keys); pair increments() with unsignedInteger() for narrower keys. Eloquent fills the timestamps() columns (Keys and Timestamps), but TIMESTAMP ends in 2038 (Date and Time Types), so datetimes() is the safer choice. The collation comes from config/database.php, overriding the server's utf8mb4_0900_ai_ci; set DB_COLLATION to change it. Every new enum() value costs an ALTER TABLE, so for statuses that grow, prefer a string cast to a PHP enum (Casting).