Skip to main content

Database: Seeding

Introduction

TinyORM includes the ability to seed your database with data using seed classes. All seed classes should be stored in the database/seeders directory. The DatabaseSeeder class is considered as the root seeder. From this class, you may use the call method to run other seed classes, allowing you to control the seeding order.

tip

Mass assignment protection is automatically disabled during database seeding.

Writing Seeders

To generate a seeder, execute the make:seeder tom command. A new seeder will be placed in the database/seeders directory relative to the current pwd:

tom make:seeder UserSeeder
tip

You can omit the Seeder word in the class name, tom appends it for you.

A seeder class only contains one method by default: run. This method is called when the db:seed tom command is executed. Within the run method, you may insert data into your database however you wish. You may use the query builder to manually insert data.

As an example, let's modify the default DatabaseSeeder class and add a database insert statement to the run method:

#pragma once

#include <tom/seeder.hpp>

namespace Seeders
{

/*! Main database seeder. */
struct DatabaseSeeder : Seeder
{
/*! Run the database seeders. */
void run() override
{
DB::table("users")->insert({"name", "email"},
{
{"1. user", "user1@example.com"},
{"2. user", "user2@example.com"},
});
}
};

} // namespace Seeders
tip

The multi-insert insert method overload is ideal for seeding data.

Calling Additional Seeders

Within the DatabaseSeeder class, you may use the call method to execute additional seed classes. Using the call method allows you to break up your database seeding into multiple files so that no single seeder class becomes too large. The call method accepts the template parameter pack of seeder classes that should be executed:

/*! Run the database seeders. */
void run() override
{
call<UserSeeder, PostSeeder, CommentSeeder>();
}

Call with additional arguments

The call method allows to pass additional arguments to the seeder/s, but it has additional requirements.

If you define a run method without parameters then this method is called using the virtual dispatch (polymorphism) and in this case, you should use the override specifier.

If you define your run method eg. like this run(bool shouldSeed) or whatever parameters you want, then this method is called using the fold expression (virtual dispatch is not used in this case) so you can't use the override specifier and you must call the call<>() method with exactly the same arguments like the run method was defined with, in our example, it should look like this call<ExampleSeeder>(true).

Let's demonstrate it on a small example, following is the run method in the root DatabaseSeeder class.

/*! Run the database seeders. */
void run() override
{
// This value can be based eg. on data from the database
const auto shouldSeed = true;

call<UserSeeder>(shouldSeed);
}

The run method in the UserSeeder class.

/*! Run the database seeders. */
void run(const bool shouldSeed)
{
if (!shouldSeed)
return;

DB::table("users")->insert({
{"name", "1. user"},
});
}
tip

The call method provides two shortcut methods, callWith and callSilent (no output from seeders).

Running Seeders

You may execute the db:seed tom command to seed your database. By default, the db:seed command runs the Seeders::DatabaseSeeder class, which may in turn invoke other seed classes. However, you may use the --class option to specify a specific seeder class to run individually:

tom db:seed

tom db:seed --class=UserSeeder

You may also seed your database using the migrate, migrate:fresh or migrate:refresh commands in combination with the --seed option. For example the migrate:fresh command drops all tables and re-run all of your migrations. This command is useful for completely re-building your database:

tom migrate:fresh --seed
tip

You can change the default seeders path as is described in the C preprocessor macros, CMake provides the TOM_SEEDERS_DIR option.

Forcing Seeders To Run In Production

Some seeding operations may cause you to alter or lose data. In order to protect you from running seeding commands against your production database, you will be prompted for confirmation before the seeders are executed in the production environment. To force the seeders to run without a prompt, use the --force flag:

tom db:seed --force