Урок 02

Создание таблиц

Метод create

Schema::create('posts', function (Blueprint $table) {
    $table->id();
    $table->string('title');
    $table->text('body');
    $table->timestamps();
});

Schema::create(имя, замыкание) — создать таблицу.

$table — объект Blueprint. Методы — колонки.

Типы колонок — полный список

Целые

$table->id();                        // BIGSERIAL PRIMARY KEY
$table->bigIncrements('id');         // BIGSERIAL без PK
$table->increments('id');            // SERIAL без PK
$table->integer('views');            // INT
$table->bigInteger('count');         // BIGINT
$table->mediumInteger('x');          // MEDIUMINT (MySQL)
$table->smallInteger('age');         // SMALLINT
$table->tinyInteger('active');       // TINYINT
$table->unsignedInteger('u');        // UNSIGNED INT
$table->unsignedBigInteger('u');     // UNSIGNED BIGINT

Строки

$table->string('name');              // VARCHAR(255)
$table->string('name', 100);         // VARCHAR(100)
$table->char('code', 4);             // CHAR(4)
$table->text('body');                // TEXT
$table->mediumText('body');          // MEDIUMTEXT
$table->longText('body');            // LONGTEXT

Числа с плавающей точкой

$table->decimal('price', 8, 2);      // DECIMAL(8,2)
$table->float('rating');             // FLOAT
$table->double('score');             // DOUBLE
$table->unsignedDecimal('x', 8, 2);

Логические

$table->boolean('is_active');        // BOOLEAN

Даты и время

$table->date('birthday');            // DATE
$table->time('starts_at');           // TIME
$table->dateTime('published_at');    // TIMESTAMP WITHOUT TZ
$table->timestamp('created_at');     // TIMESTAMP
$table->timestamps();                // created_at + updated_at
$table->softDeletes();               // deleted_at
$table->timestampsTz();              // с таймзоной
$table->year('year');                // YEAR (MySQL)
$table->timeTz('t');
$table->dateTimeTz('dt');

Специальные

$table->json('options');             // JSON
$table->jsonb('meta');               // JSONB (PostgreSQL)
$table->binary('data');              // BLOB
$table->uuid('uuid');                // UUID
$table->ulid('ulid');                // ULID
$table->ipAddress('ip');             // IP (VARCHAR)
$table->macAddress('mac');           // MAC
$table->rememberToken();             // remember_token
$table->morphs('taggable');          // taggable_id + taggable_type
$table->nullableMorphs('x');         // nullable версия
$table->uuidMorphs('x');

Внешние ключи

$table->foreignId('user_id');        // BIGINT для FK
$table->foreignUuid('user_uuid');    // UUID для FK
$table->foreignUlid('user_ulid');

Enum

$table->enum('status', ['draft', 'published', 'archived']);

Полный пример

Schema::create('posts', function (Blueprint $table) {
    $table->id();
    $table->foreignId('user_id')->constrained()->cascadeOnDelete();
    $table->string('title');
    $table->string('slug')->unique();
    $table->text('body');
    $table->enum('status', ['draft', 'published'])->default('draft');
    $table->integer('views')->default(0);
    $table->boolean('featured')->default(false);
    $table->json('meta')->nullable();
    $table->timestamp('published_at')->nullable();
    $table->timestamps();
    $table->softDeletes();
});

Проверка существования

if (Schema::hasTable('posts')) { }
if (Schema::hasColumn('posts', 'title')) { }
if (Schema::hasColumns('posts', ['title', 'body'])) { }

Удаление

Schema::drop('posts');                // упадёт, если нет
Schema::dropIfExists('posts');        // безопасно
Schema::dropColumns('posts', ['a', 'b']);
Schema::dropAllTables();              // все (dev only)

Переименование

Schema::rename('posts', 'articles');

Практика

Миграция для блога:

Schema::create('posts', function (Blueprint $table) {
    $table->id();
    $table->foreignId('user_id')->constrained()->cascadeOnDelete();
    $table->foreignId('category_id')->nullable()->constrained()->nullOnDelete();
    $table->string('title');
    $table->string('slug')->unique();
    $table->text('excerpt')->nullable();
    $table->longText('body');
    $table->enum('status', ['draft', 'published', 'archived'])->default('draft');
    $table->integer('views_count')->default(0);
    $table->boolean('is_featured')->default(false);
    $table->json('tags')->nullable();
    $table->timestamp('published_at')->nullable()->index();
    $table->timestamps();
    $table->softDeletes();

    $table->index(['status', 'published_at']);
});

Проверка:

php artisan migrate
php artisan db:show --table=posts

Частые ошибки

1. string без длины для больших текстов:

$table->string('body');   // VARCHAR(255) — обрежет длинный текст

// Правильно:
$table->text('body');

2. foreignId без constrained:

$table->foreignId('user_id');   // только BIGINT, без FK

// Правильно:
$table->foreignId('user_id')->constrained();

3. Забыли nullable:

$table->string('bio');   // NOT NULL → ошибка при пустом

4. json без default:

$table->json('meta');   // NOT NULL

// Правильно:
$table->json('meta')->nullable();

5. timestamps только в конце:

Принято, но не обязательно. Главное — не забыть.

Итог

  • Schema::create(имя, fn($table) => ...).
  • Типы: id, string, text, integer, boolean, json, timestamps.
  • foreignId()->constrained() — FK.
  • softDeletes() — для мягкого удаления.
  • nullable — для необязательных.
  • default — значение по умолчанию.
  • Правило: строка → string, длинный текст → text.

Дальше — модификаторы колонок.