PHPackages                             vherbaut/laravel-data-migrations - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. vherbaut/laravel-data-migrations

ActiveLibrary

vherbaut/laravel-data-migrations
================================

Versioned data migrations for Laravel - transform, backfill, and migrate your data with the same elegance as schema migrations.

1.0.3(4mo ago)062—0%MITPHPPHP ^8.2CI passing

Since Dec 28Pushed 1mo agoCompare

[ Source](https://github.com/vherbaut/laravel-data-migrations)[ Packagist](https://packagist.org/packages/vherbaut/laravel-data-migrations)[ Docs](https://github.com/vherbaut/laravel-data-migrations)[ RSS](/packages/vherbaut-laravel-data-migrations/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (6)Dependencies (8)Versions (6)Used By (0)

Laravel Data Migrations
=======================

[](#laravel-data-migrations)

> **[Lire en Français](README-FR.md)**

[![Latest Version on Packagist](https://camo.githubusercontent.com/7cb17c070ab61963ee63902ce5642042faca5010e8a16a2ad3c1b26f27d55853/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f76686572626175742f6c61726176656c2d646174612d6d6967726174696f6e732e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/vherbaut/laravel-data-migrations)[![Tests](https://camo.githubusercontent.com/494cd056c04aaa2cd45948a50886afe444cab0bb3d5d6e638ba9b6ceef9f7760/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f76686572626175742f6c61726176656c2d646174612d6d6967726174696f6e732f74657374732e796d6c3f6272616e63683d6d61696e266c6162656c3d7465737473267374796c653d666c61742d737175617265)](https://github.com/vherbaut/laravel-data-migrations/actions/workflows/tests.yml)[![PHPStan](https://camo.githubusercontent.com/4470f8df20a6d13b9eac69d9a1f3abcd72eb30f8436f5355e69f06cb6bd970ab/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048505374616e2d6c6576656c253230352d627269676874677265656e2e7376673f7374796c653d666c61742d737175617265)](https://phpstan.org/)[![Total Downloads](https://camo.githubusercontent.com/6d8d0cf747f42d270006479536c390d27cef1a93f957c569dc15c17c19aea959/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f76686572626175742f6c61726176656c2d646174612d6d6967726174696f6e732e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/vherbaut/laravel-data-migrations)[![License](https://camo.githubusercontent.com/49c2814ae600b4f8c65b6405c801eed052096d09d9ecc1a9f656cc1f378b4bd8/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f76686572626175742f6c61726176656c2d646174612d6d6967726174696f6e732e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/vherbaut/laravel-data-migrations)

**Versioned data migrations for Laravel.** Transform, backfill, and migrate your data with the same elegance as schema migrations.

---

Table of Contents
-----------------

[](#table-of-contents)

- [Why Data Migrations?](#why-data-migrations)
- [Data Migrations vs Seeders](#data-migrations-vs-seeders)
- [Features](#features)
- [Requirements](#requirements)
- [Installation](#installation)
- [Quick Start](#quick-start)
- [Console Commands](#console-commands)
- [Writing Data Migrations](#writing-data-migrations)
- [Configuration](#configuration)
- [Safety Features](#safety-features)
- [Real-World Examples](#real-world-examples)
- [Architecture](#architecture)
- [Testing](#testing)
- [Best Practices](#best-practices)
- [Contributing](#contributing)
- [License](#license)

---

Why Data Migrations?
--------------------

[](#why-data-migrations)

Laravel's schema migrations handle database structure changes beautifully, but what about data transformations? Currently, developers resort to:

- **Putting data logic in schema migrations** — Mixing concerns, hard to rollback
- **One-off artisan commands** — Not versioned, forgotten, impossible to replay
- **Manual SQL in production** — Dangerous and undocumented

**Data Migrations** solve this by providing a structured, versioned approach to data transformations.

---

Data Migrations vs Seeders
--------------------------

[](#data-migrations-vs-seeders)

A common question: *"Why not just use Laravel Seeders?"*

Seeders and Data Migrations serve **fundamentally different purposes**:

AspectSeedersData Migrations**Purpose**Populate dev/test dataTransform production data**Environment**Development, testingProduction, staging**Tracking**None - can run multiple timesVersioned - runs once per environment**Rollback**Not supportedFull rollback support**History**No record of executionComplete audit trail (when, rows affected, duration)**Team sync**Manual coordinationAutomatic - like schema migrations**Progress**No feedbackProgress bars, row counts**Safety**No safeguardsDry-run, confirmations, backups\**\*Backup feature requires [spatie/laravel-backup](https://github.com/spatie/laravel-backup)*

### When to use Seeders

[](#when-to-use-seeders)

```
// Seeders: Populate test data for development
class UserSeeder extends Seeder
{
    public function run(): void
    {
        User::factory()->count(100)->create();  // Creates fake users
    }
}
```

Use seeders when you need to:

- Generate fake data for local development
- Reset your database to a known state
- Create test fixtures

### When to use Data Migrations

[](#when-to-use-data-migrations)

```
// Data Migrations: Transform real production data
return new class extends DataMigration
{
    protected string $description = 'Migrate legacy status values to new enum';

    public function up(): void
    {
        // Transforms existing production data
        DB::table('orders')
            ->where('status', 'pending_payment')
            ->update(['status' => 'awaiting_payment']);

        $this->affected(DB::table('orders')->where('status', 'awaiting_payment')->count());
    }

    public function down(): void
    {
        DB::table('orders')
            ->where('status', 'awaiting_payment')
            ->update(['status' => 'pending_payment']);
    }
};
```

Use data migrations when you need to:

- Transform existing production data
- Backfill new columns with calculated values
- Normalize or clean up legacy data
- Migrate data between schema changes
- Ensure all team members/environments apply the same data changes

### The Problem with Using Seeders for Data Transformations

[](#the-problem-with-using-seeders-for-data-transformations)

```
// DON'T DO THIS - Using seeders for production data changes
class FixUserEmailsSeeder extends Seeder
{
    public function run(): void
    {
        // Problems:
        // 1. No tracking - might run twice and corrupt data
        // 2. No rollback if something goes wrong
        // 3. No audit trail - when was this run? By whom?
        // 4. Team members don't know if they need to run it
        // 5. No progress feedback on large datasets
        DB::table('users')->update([
            'email' => DB::raw('LOWER(email)')
        ]);
    }
}
```

**Data Migrations solve all these problems** by treating data changes with the same rigor as schema changes.

---

Features
--------

[](#features)

FeatureDescription**Versioned Migrations**Track data changes just like schema migrations**Separate from Schema**Keep data logic independent from structure changes**Rollback Support**Reverse data changes when needed**Dry-Run Mode**Preview what will happen before execution**Progress Tracking**Visual progress bars for long-running operations**Chunked Processing**Process millions of rows without memory issues**Production Safety**Built-in confirmations and force flags**Transaction Support**Automatic transaction wrapping with configurable modes**Auto Backup**Optional automatic backup before migrations (requires [spatie/laravel-backup](https://github.com/spatie/laravel-backup))**Timeout Control**Configurable execution time limits**Row Threshold Alerts**Confirmation prompts for large operations**PHPStan Level 5**Fully typed, strict static analysis compliance---

Requirements
------------

[](#requirements)

- PHP 8.2 or higher
- Laravel 10.x, 11.x, or 12.x
- A supported database (MySQL, PostgreSQL, SQLite, SQL Server)

---

Installation
------------

[](#installation)

Install the package via Composer:

```
composer require vherbaut/laravel-data-migrations
```

Publish the configuration file:

```
php artisan vendor:publish --tag=data-migrations-config
```

Run the migrations to create the tracking table:

```
php artisan migrate
```

### Optional: Publish Stubs

[](#optional-publish-stubs)

Customize the migration templates:

```
php artisan vendor:publish --tag=data-migrations-stubs
```

---

Quick Start
-----------

[](#quick-start)

### 1. Create a Data Migration

[](#1-create-a-data-migration)

```
php artisan make:data-migration split_user_names
```

This creates `database/data-migrations/2024_01_15_123456_split_user_names.php`:

```
