laraveldatabase-migrationdata-migrationconceptual

Recommended / Standard handling of Laravel Data Migrations


Laravel ships with database migrations for managing CRUD operations regarding the structure of a database, but what is the appropriate/recommended/standardized way to handle migration of actual data?

My question is, should the data migration take place directly inside the database migration file? Should it be a seeder? Should it be a job that is dispatched from within the database migration? Where should such logic go. Sometimes these data migrations can become incredibly complex depending on what the database migration does, and in the spirit of maximizing readability and keeping responsibilities separate, I feel like the logic belongs somewhere else.

This question, I suppose, is more attributable to OOP programming structure and practice as a whole, rather than laravel specific, but Laravel is the framework I'm working in right now so framing my question in that regard.


Solution

  • I've done this several times, and I do it right there in the migration up() and down() functions unless we're talking about millions of records. I agree with you, it feels like there should be a clearly defined function in the migration for this. We want the data changed before another migration on the table is triggered, so I feel it needs to be done right away.

    Using your example, this is what a simple migration would look like for splitting the name into a first_name and last_name in the up() function:

    <?php
    
    use Illuminate\Database\Migrations\Migration;
    use Illuminate\Database\Schema\Blueprint;
    use Illuminate\Support\Facades\Schema;
    use Illuminate\Support\Facades\DB;
    
    class Test extends Migration
    {
        /**
         * Run the migrations.
         *
         * @return void
         */
        public function up()
        {
            Schema::table('users', function (Blueprint $table) {
                $table->string('last_name')->after('name');
                $table->string('first_name')->after('name');
            });
    
            DB::statement("UPDATE users SET first_name = SUBSTRING_INDEX(name, ' ', 1), last_name = SUBSTRING(name from instr(name, ' ') + 1)");
    
            Schema::table('users', function (Blueprint $table) {
                $table->dropColumn('name');
            });
        }
    
    ...
    

    If you have complex data changes, take a look at the $table->temporary(); option to create temporary tables to do data manipulation with SQL, and/or make command scripts which are called within the migration using the Artisan::call().

    $table->temporary(): https://laravel.com/docs/8.x/migrations#database-connection-table-options Artisan::call(): https://laravel.com/docs/8.x/artisan#programmatically-executing-commands