Laravel:Migrations & Seeding for Production Data

Laravel : Migrations & Seeding for production data

Laravel development is about freedom. So, if you need to seed your production database and think DatabaseSeeder is the best place to do so, why not?

Okay, seeder is mainly to be used with test data, but you'll see some folks using it as you are.

I see this important kind of seed as part of my migration, since this is something that cannot be out of my database tables and artisan migrate is ran everytime I deploy a new version of my application, so I just do

php artisan migrate:make seed_models_table

And create my seedind stuff in it:

public function up()
{
$models = array(
array('name' => '...'),
);

DB::table('models')->insert($models);
}

Populating tables in production with Laravel

How should we proceed (where to put the code) when we need to populate data for production?

Our team makes a brand new migration for inserting production seeds (separate from the migration that creates the table). That way, if you need to add more seeds to your production data in the future, you can simply make a new standalone migration.

For example, your first migration could be 2016_03_05_213904_create_permissions_table.php, followed by your production seeds: 2016_03_05_214014_seed_permissions_table.php.

You could put this data in the same migration as your table creation, but in my opinion, the migration becomes less readable and arguably violates SRP. If you needed to add more seeds in the future, you would have two different "standards" (one group of seeds in your original migration, and another in a separate migration).

To answer your second question:

What mechanism should we use for inserting data?

I would always use your model's create() method for inserting production seeds. This ensures that any event listeners that are listening for your model's creation event properly fire. As you said, there could be extra code that needs to fire when your model is created.


How to properly handle database data changes with laravel migrations and seeds

From your explanation, I think I understand.

The first thing your seeders should do is delete everything so you always start with an empty database, at least where the seeders should be concerned.

I'd also take a closer look at the docs https://laravel.com/docs/5.2/seeding specifically the section "Using Model Factories".

public function run()
{
factory(App\User::class, 50)->create()->each(function($u) {
$u->posts()->save(factory(App\Post::class)->make());
});
}

In this case, you'd do something similar except you'd start at the top which for you is user_types, then for each type it creates, it would generate however many users you need. This seems a bit different from your current process where it sounds like you have a seeder file for each table.

This way, you have the parent/child relationships handled and made very clear in the code and it's very easy to add additional items in the future. Additionally, because you are essentially starting from scratch each time the seeders run, you can be sure this will work for new and existing devs.

Laravel: Running a database migration on a production server

As already mentioned, you can create migrations to update the columns without dropping the tables. And the 'Modifying columns' docs provide a clear explanation for this. However that is docs for modifying columns, if you want to modify tables instead of columns, you can use the 'Updating tables' docs

This uses the SchemaBuilder to do various things, for example, adding columns in an existing table:

Schema::table('table_name'), function ($table) {
$table->string('new_column')->after('existing_column');
// however you can leave the ->after() part out, this just specifies that the
// new column should be insterted after the specified column.
});

Or delete a column from an existing table

Schema::table('table_name'), function ($table) {
$table->dropColumn('new_column');
});

You can also rename but I'll leave it to you to explore the docs further.

Recommended / Standard handling of Laravel Data Migrations

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

Database gets stuck in migration with seeder on production with --force in Laravel 5

Try including the -vvv flag in your migration command, this will increase the verbosity of any messages, which might uncover the problem.

--verbose (-v|vv|vvv) Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug

$ php artisan migrate --force

As for the problem itself, try including the --force flag in your db:seed call, as you have included it in the migration.

Artisan::call('db:seed', ['--class' => 'ProductsSeeder', '--force' => true,]);

Laravel seed after migrating

You can call migrate:refresh with the --seed option to automatically seed after the migrations are complete:

php artisan migrate:refresh --seed

This will rollback and re-run all your migrations and run all seeders afterwards.


Just as a little extra, you can also always use Artisan::call() to run an artisan command from inside the application:

Artisan::call('db:seed');

or

Artisan::call('db:seed', array('--class' => 'YourSeederClass'));

if you want specific seeder class.



Related Topics



Leave a reply



Submit