Seeding – inside of the migration files

Laravel has quite a convenient mechanism of dealing with database changes. It consists of Migration files for database structure and Seed files for sample data. But why separate them if sometimes it make sense to add it all to one file?

Let’s say we are creating a new DB table called categories and we know from the beginning that there will be only three categories: “first”, “second” and “third”.

Option 1: separate migrations and seeds

In theory, we should create migration and seed files separately, like this:

1. Migration file:

php artisan make:migration create_categories_table

Then within the file itself:

	public function up()
	{
		Schema::create('categories', function(Blueprint $table)
		{
			$table->increments('id');
			$table->string('title');
			$table->timestamps();
		});
	}

2. Then Model – app/Category.php:

class Category extends Model
{
    protected $fillable = ['title'];
}

3. And then Seed file

php artisan make:seeder CategoryTableSeeder

And within Seed file:

    public function run()
    {
    	$categories = ['first', 'second', 'third'];
        foreach ($categories as $category) 
	        Category::create(['title' => $category]);
    }

Option 2: seeding in migration file

In previous option, to launch all of that you have to launch separately artisan migrate and artisan db:seed, and probably add some code in seeding to check if those categories had not been inserted before. Personally, I like to “break the rules” and put seeding code directly into the migration file. Like this:

	public function up()
	{
		Schema::create('categories', function(Blueprint $table)
		{
			$table->increments('id');
			$table->string('title');
			$table->timestamps();
		});

    	$categories = ['first', 'second', 'third'];
        foreach ($categories as $category) 
	        Category::create(['title' => $category]);
	}

And then – just artisan migrate and you have both table structure and seeding data.

Notice: of course, Category model has to be created before that.

The thing is that migration file and up() function can contain whatever code you want, not just Schema sentences. In theory, you can do something more – log something, add try-catch blocks etc.

I would advice something like that for simple few lines of data, where it’s a small table. For more complex seeding with more fields/rows it does make sense to separate that action into seeds, taking care of checking if the table is empty etc.

What do you think about such method – more convenient, in my opinion, but maybe you know any drawbacks?

Like our articles?
Check out our Laravel online courses!

10 COMMENTS

  1. The biggest issue I find is consistency. Now some resources are seeded in the migration file, and some are seeded in seed files. I’m actually working on a project where there is initial seed data in the migration files. What seemed like an innocent little rule break has turned into a headache. Where does it end?

    I find it much easier to make a rule that seed data goes into seed files, instead of implementing an immutable seed data goes into migrations and other seed data goes into seed files. I prefer black and white rules, leaving very little to interpretation. I also find that a strict rule approach works better the larger your dev team is.

    I find the approach of adding seed data to migrations very similar to bypassing controllers and putting your logic in the routes file. Sure you can do it, and for small projects it might be a quick little time saver. But, if you’re building anything of substance, you are going to want better structure.

  2. When unit testing, there are some tests where I don’t need the DB to be touched at all, some where I need the structure but no data, and some where i need data to be seeded too. Maybe this is a deificiency in my approach to testing, but putting seeds in with the migrations means I loseone of these options.

  3. If you want to have structure and data in one command you could also use

    php artisan migrate –seed

    Its also nice for development, if you want to reset your database:

    php artisan migrate:refresh –seed

    Greetings

  4. I think it’s mandatory to mention model factories (available from Laravel 5.1) here, as they are a very good point to start seeding process from. Combining these factories with Faker helps to populate a database with nearly any type of test data really easily. More information here – http://laravel.com/docs/5.1/seeding#using-model-factories .

    What’s about combining migrations and seeds into one file. I think that consistency is not the only problem here. There could be lots of situations when you only need to work with the database structure (rolling it back or something), and when you want just seed your test data into current database. So really I don’t think this approach is really good, but of course, everything depends on the specific project 🙂

  5. Great tut!
    I just copy the “php artisan db:seed” created code to the “up()” function.

    Thanks

    btw, I tried “php artisan migrate:refresh –seed” with Laravel 5.3 and does not work.

  6. Despite the other comments. I do actually agree with your habit.

    I use migrations and seeds for different purposes.
    I think data that should be added in production (not for testing or faker data for dev), should be part of the migrations. Especially the data that can not be edited in the app itself. If you like you can put it in a seeder and call it from the migration.
    Having it in the migration also makes sure it will be ran as part of that migration and not in the end after the whole thing has set.

    One thing that is potentially dangerous though is using Models in your migration, you should use DB::insert there, as the model can change over time and become incompatible with the database structure at the point of your migration (e.g. added required properties). Someone that wants to spin up the application after some years will get into trouble and that is against the purpose of keeping a history with migrations (unfortunately there is no accompanying history for the models, apart from version control).

LEAVE A REPLY

Please enter your comment!
Please enter your name here