LaravelJuniorTechnical

Что такое migrations в Laravel и как их создавать и запускать?

Миграции — версионный контроль схемы БД. Создаются через artisan make:migration, описывают изменения в методах up()/down(), применяются командой php artisan migrate.

Миграции в Laravel

Миграции — это версионный контроль для схемы базы данных. Каждая миграция представляет собой PHP-класс с двумя методами: up() — применить изменение, down() — откатить его. Laravel хранит список уже применённых миграций в таблице migrations.

Создание миграции

# Создать таблицу
php artisan make:migration create_products_table

# Изменить существующую таблицу
php artisan make:migration add_price_to_products_table --table=products

Файл появится в database/migrations/ с временной меткой в имени — это гарантирует порядок выполнения.

Структура файла миграции

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    public function up(): void
    {
        Schema::create('products', function (Blueprint $table) {
            $table->id();                          // BIGINT UNSIGNED AUTO_INCREMENT PK
            $table->string('name', 200);
            $table->text('description')->nullable();
            $table->decimal('price', 10, 2)->default(0);
            $table->foreignId('category_id')
                  ->constrained()
                  ->cascadeOnDelete();
            $table->timestamps();                  // created_at + updated_at
            $table->softDeletes();                 // deleted_at
        });
    }

    public function down(): void
    {
        Schema::dropIfExists('products');
    }
};

Основные команды

# Применить все новые миграции
php artisan migrate

# Откатить последний пакет миграций
php artisan migrate:rollback

# Откатить все и применить заново (для dev)
php artisan migrate:fresh

# Откатить все, применить и запустить сидеры
php artisan migrate:fresh --seed

# Показать статус всех миграций
php artisan migrate:status

Добавление колонки к существующей таблице

public function up(): void
{
    Schema::table('products', function (Blueprint $table) {
        $table->unsignedInteger('stock')->default(0)->after('price');
        $table->index('category_id'); // добавить индекс
    });
}

public function down(): void
{
    Schema::table('products', function (Blueprint $table) {
        $table->dropColumn('stock');
    });
}

Подводные камни

  • migrate:fresh удаляет ВСЕ таблицы — никогда не запускайте его в production, только в разработке.
  • Не редактируйте уже применённые миграции: если коллеги уже сделали migrate, изменение файла не повлияет на их БД. Создавайте новую миграцию.
  • Метод down() должен полностью обращать up(); если вы добавили индекс в up(), в down() его нужно явно дропнуть через dropIndex().
  • При добавлении NOT NULL колонки в таблицу с существующими данными без default значения — база данных вернёт ошибку. Всегда задавайте ->nullable() или ->default(...).
  • Имя файла (и класса) миграции должно быть уникальным; дублирующиеся имена приводят к конфликтам при autoload.
  • foreignId('category_id')->constrained() по умолчанию ищет таблицу categories — если она называется иначе, укажите явно: constrained('product_categories').
  • В SQLite ряд операций Schema (например, dropColumn для некоторых типов) не поддерживается — учитывайте это при написании тестов с in-memory SQLite.

Common mistakes

  • Сводить migrations к названию метода без lifecycle и failure path.
  • Игнорировать модель runtime: Laravel 13 поверх PHP: request проходит через HTTP kernel, middleware, routing, controller/action и response pipeline.
  • Не отделять validation, authorization, transaction boundary и business logic.

What the interviewer is testing

  • Объясняет migrations через конкретную точку lifecycle в Laravel.
  • Приводит корректный минимальный пример без вымышленных методов или callbacks.
  • Называет edge cases: пустые значения, ошибки, транзакции, безопасность или concurrency.

Sources

Related topics