> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Database migrations

> Learn how to version-control your database schema using Laravel's migration feature.

## What are migrations

Migrations are like version control for your database.
They let your team share and manage the application's database schema definition.

You've likely experienced situations where, after pulling source code, you have to tell teammates: "please manually add this column to your local database."
Migrations solve that problem.

Migration files are stored in the `database/migrations` directory.
Each file name includes a timestamp, which Laravel uses to determine the order in which migrations are run.

## Creating a migration file

Generate a new migration file with the `make:migration` Artisan command.

```shell theme={null}
php artisan make:migration create_posts_table
```

Laravel infers the table name from the migration name and generates an appropriate stub.
With a name like `create_posts_table`, code to create a `posts` table is scaffolded for you.

## Migration structure

A migration class has two methods: `up` and `down`.

* `up` method: Adds tables, columns, and indexes to the database.
* `down` method: Reverses the operations in `up`. Called during rollback.

```php theme={null}
<?php

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

return new class extends Migration
{
    /**
     * Run the migration.
     */
    public function up(): void
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->id();
            $table->string('title');
            $table->text('body');
            $table->boolean('published')->default(false);
            $table->timestamps();
        });
    }

    /**
     * Reverse the migration.
     */
    public function down(): void
    {
        Schema::dropIfExists('posts');
    }
};
```

## Common column definition methods

The `Blueprint` class provides many column types.

| Method                              | Description                                                     |
| ----------------------------------- | --------------------------------------------------------------- |
| `$table->id()`                      | Auto-incrementing primary key (alias for `bigIncrements('id')`) |
| `$table->string('name')`            | VARCHAR-equivalent column (default 255 characters)              |
| `$table->text('body')`              | TEXT column                                                     |
| `$table->integer('count')`          | INTEGER column                                                  |
| `$table->boolean('active')`         | Stores a boolean as TINYINT                                     |
| `$table->timestamp('published_at')` | TIMESTAMP column                                                |
| `$table->timestamps()`              | Adds `created_at` and `updated_at` together                     |
| `$table->softDeletes()`             | Adds a `deleted_at` column for soft deletes                     |
| `$table->foreignId('user_id')`      | BIGINT UNSIGNED column for a foreign key                        |

### Column modifiers

You can chain modifiers to a column definition.

```php theme={null}
$table->string('email')->unique();
$table->string('name')->nullable();
$table->integer('votes')->default(0);
$table->string('title')->after('id'); // Place after the specified column
```

## Running migrations

Use the `migrate` command to run all pending migrations.

```shell theme={null}
php artisan migrate
```

Use `migrate:status` to see which migrations have and have not run.

```shell theme={null}
php artisan migrate:status
```

<Warning>
  Running migrations in production shows a confirmation prompt.
  To run without confirmation, use the `--force` flag, but be careful because some operations can lose data.
</Warning>

## Rollbacks

Use `migrate:rollback` to undo the last batch of migrations.

```shell theme={null}
php artisan migrate:rollback
```

To roll back a specific number of steps, use the `--step` option.

```shell theme={null}
# Roll back the last 5 migrations
php artisan migrate:rollback --step=5
```

To roll back all migrations and re-run them, use `migrate:refresh`.

```shell theme={null}
php artisan migrate:refresh
```

<Info>
  `migrate:refresh` recreates all tables, so all existing data is lost.
  It's handy for resetting your database during development.
</Info>

## Practical example: creating the posts table

Walk through the entire flow using a `posts` table that stores blog posts.

### 1. Generate the migration file

```shell theme={null}
php artisan make:migration create_posts_table
```

### 2. Edit the migration

Open and edit `database/migrations/xxxx_xx_xx_xxxxxx_create_posts_table.php`.

```php theme={null}
<?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('posts', function (Blueprint $table) {
            $table->id();
            $table->foreignId('user_id')->constrained()->cascadeOnDelete();
            $table->string('title');
            $table->text('body');
            $table->boolean('published')->default(false);
            $table->timestamp('published_at')->nullable();
            $table->timestamps();
        });
    }

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

### 3. Run the migration

```shell theme={null}
php artisan migrate
```

Once run, the `posts` table is created in the database.

### 4. Adding a column later

To add new columns after a table has been created, don't edit the existing migration—create a new migration.

```shell theme={null}
php artisan make:migration add_excerpt_to_posts_table
```

```php theme={null}
public function up(): void
{
    Schema::table('posts', function (Blueprint $table) {
        $table->string('excerpt')->nullable()->after('title');
    });
}

public function down(): void
{
    Schema::table('posts', function (Blueprint $table) {
        $table->dropColumn('excerpt');
    });
}
```

<Tip>
  Avoid editing existing migration files directly.
  Doing so breaks consistency with other teammates and production environments.
  Always add changes as a new migration.
</Tip>

## Migration events

An [event](/en/events) is dispatched for each migration operation. All events extend `Illuminate\Database\Events\MigrationEvent`.

| Class                                            | Description                                                         |
| ------------------------------------------------ | ------------------------------------------------------------------- |
| `Illuminate\Database\Events\DatabaseRefreshed`   | After the `migrate:refresh` command completes                       |
| `Illuminate\Database\Events\MigrationsStarted`   | Immediately before a batch of migrations runs                       |
| `Illuminate\Database\Events\MigrationsEnded`     | After a batch of migrations completes                               |
| `Illuminate\Database\Events\MigrationStarted`    | Immediately before a single migration runs                          |
| `Illuminate\Database\Events\MigrationEnded`      | After a single migration completes                                  |
| `Illuminate\Database\Events\NoPendingMigrations` | When a migration command determines there are no pending migrations |
| `Illuminate\Database\Events\SchemaDumped`        | After a database schema dump completes                              |
| `Illuminate\Database\Events\SchemaLoaded`        | After loading an existing schema dump                               |

For example, you can listen for the `MigrationsEnded` event to clear caches after migrations finish.

```php theme={null}
use Illuminate\Database\Events\MigrationsEnded;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Event;

Event::listen(MigrationsEnded::class, function () {
    Cache::flush();
});
```

## Next steps

<Card title="Database seeding" icon="seedling" href="/en/seeding">
  Learn how to populate the tables created by migrations with sample data.
</Card>

<Card title="Eloquent introduction" icon="database" href="/en/eloquent">
  Learn how to interact with the tables you created via migrations using the Eloquent ORM.
</Card>


## Related topics

- [Database Testing](/en/database-testing.md)
- [Laravel Pennant](/en/pennant.md)
- [Develop Laravel packages with Testbench Workbench](/en/advanced/package-workbench.md)
- [Advanced Testing with Pest](/en/advanced/testing-pest.md)
- [Directory structure](/en/directory-structure.md)
