> ## 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

> How to use Laravel migrations to version-control your database schema and share it with your team.

## What are migrations?

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

If you have ever had to tell a teammate to manually add a column to their local database after pulling your changes, migrations solve exactly that problem.

Migration files are stored in the `database/migrations` directory. Each filename contains a timestamp that Laravel uses to determine the order in which to run the migrations.

## Creating a migration

Use the `make:migration` Artisan command to generate a new migration file:

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

Laravel infers the table name from the migration name and generates an appropriate stub. A name like `create_posts_table` produces a stub that creates the `posts` table.

## Migration structure

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

* **`up`** — adds tables, columns, or indexes to the database.
* **`down`** — reverses the operations performed by `up`. Called when rolling back.

```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 migrations.
     */
    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 migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('posts');
    }
};
```

## Available column types

The `Blueprint` class provides many column type methods:

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

### Column modifiers

Chain modifier methods to customize column definitions:

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

## Running migrations

Run all pending migrations with the `migrate` command:

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

To check which migrations have run and which are pending:

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

<Warning>
  Running migrations in production will prompt you to confirm. Use the `--force` flag to skip the prompt, but be careful — some operations are destructive.
</Warning>

## Rolling back migrations

Roll back the most recent batch of migrations with `migrate:rollback`:

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

Roll back a specific number of migrations with 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:

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

<Info>
  `migrate:refresh` drops and recreates all tables, so any existing data is lost. It is useful for resetting your database during development.
</Info>

## Practical example: creating a posts table

Here is the complete workflow for creating a `posts` table for a blog application.

### 1. Generate the migration file

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

### 2. Edit the migration

Open `database/migrations/xxxx_xx_xx_xxxxxx_create_posts_table.php` and define the schema:

```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
```

After running the command, the `posts` table is created in your database.

### 4. Adding a column later

When you need to add a column after a table has already been created, create a new migration instead of modifying the existing one:

```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>
  Never modify an existing migration file that has already been run. Doing so breaks consistency with your teammates and with production. Always add changes as a new migration.
</Tip>

## Next steps

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

<Card title="Eloquent ORM" icon="database" href="/en/eloquent">
  Learn how to interact with the tables you created using Eloquent.
</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)
