You must have just started development of a Laravel based project and you need to fill it with data. Laravel includes a simple method of seeding your database with test data using seed classes. All seed classes are stored in the database/seeds directory…
Database Seeding is important when developing applications whether it’s going to be a small app or a large scale application.
To create a Seeder the make:seeder
artisan command is executed. Read Laravel docs here for more instructions
php artisan make:seeder TestSeeder
A model Factory is generated by executing the make:factory
artisan command.
php artisan make:factory PostFactory --model=Post
Read more here about using model factories in Laravel.
Let’s seed a simple Film sharing and commenting application, where users can share films belonging to a particular genre. So there will be a User, Film, Comment and Genre Model .
Laravel default comes with a User model and migration which is good enough for this example. Let’s go ahead and create the other models and migration.
php artisan make:model Film -m
## create film model and migration
php artisan make:model Comment -m
## create comment model and migration
php artisan make:model Genre -m
## create genre model and migration
User migration and model factory comes prewritten … so we can skip …
Write Genre Migration and Factory
// Genre Migration
public function up()
{
Schema::create('genres', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->timestamps();
});
}
php artisan make:factory GenreFactory --model=Genre
// Genre Factory
<?php
use Faker\Generator as Faker;
$factory->define(App\Genre::class, function (Faker $faker) {
return [
'name' => $faker->word,
];
});
Write Film Migration and Factory
//Film Migration
public function up()
{
Schema::create('films', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id');
$table->string('title');
$table->text('description');
$table->date('release_date');
$table->enum('rating',[ 1, 2, 3, 4, 5] );
$table->integer('genre_id');
$table->string('photo');
$table->string('slug');
$table->timestamps();
});
}
php artisan make:factory FilmFactory --model=Film
<?php
use Faker\Generator as Faker;
$factory->define(App\Film::class, function (Faker $faker) {
return [
'title' => $faker->sentence(5),
'description' => $faker->realText(rand(80, 600)),
'release_date' => $faker->date(),
'rating' => rand(1,5),
'genre_id' => function () {
// Get random genre id
return App\Genre::inRandomOrder()->first()->id;
},
'photo' => 'https://via.placeholder.com/350x150',
'slug' => str_replace('--', '-', strtolower(preg_replace('/[^a-zA-Z0-9]/', '-', trim($faker->sentence(5))))),
];
});
*Write Comment Migration and Factory *
// Comment Migration
public function up()
{
Schema::create('comments', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id');
$table->integer('film_id');
$table->text('comment');
$table->timestamps();
});
}
php artisan make:factory CommentFactory --model=Comment
<?php
use Faker\Generator as Faker;
$factory->define(App\Comment::class, function (Faker $faker) {
return [
'comment' => $faker->realText(rand(10, 300)),
];
});
php artisan make:seeder GenreTableSeeder
public function run()
{
// How many genres you need, defaulting to 10
$count = (int)$this->command->ask('How many genres do you need ?', 10);
$this->command->info("Creating {$count} genres.");
// Create the Genre
$genres = factory(App\Genre::class, $count)->create();
$this->command->info('Genres Created!');
}
php artisan make:seeder UserFilmSeeder
Since this is a film sharing application, every user tends to share a certain number of film on this app. So our seeder should look like …
public function run()
{
// How many genres you need, defaulting to 10
$userCount = (int)$this->command->ask('How many users do you need ?', 10);
// Ask range for film per user needed
$r = 0 . '-' . 10;
$filmRange = $this->command->ask('How many films per user do you need ?', $r);
$this->command->info("Creating {$userCount} users each having a film range of {$filmRange}.");
// Create the Users
$users = factory(App\User::class, $userCount)->create();
// Create a range of films for each users
$users->each(function($user) use ($filmRange){
factory(App\Film::class, $this->count($filmRange))
->create(['user_id' => $user->id]);
});
$this->command->info('Users and Films Created!');
}
// Return random value in given range
function count($range)
{
return rand(...explode('-', $range));
}
php artisan make:seeder CommentTableSeeder
public function run()
{
$r = 0 . '-' . 10;
$commentRange = $this->command->ask('How many comments per film do you need ?', $r);
$films = App\Film::all();
$this->command->info("Creating a range of {$commentRange} comments for {$films->count()} films .");
$films->each(function($film) use ($commentRange){
factory(App\Comment::class, $this->count($commentRange))
->create([
'film_id' => $film->id,
'user_id' => App\User::all()->random()->id
]);
});
$this->command->info('Comments Created!');
}
// Return random value in given range
function count($range)
{
return rand(...explode('-', $range));
}
Let’s invoke generated seeders in the DatabaseSeeder
class using the call
method
<?php
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
public function run()
{
Eloquent::unguard();
// Ask for db migration refresh, default is no
if ($this->command->confirm('Do you wish to refresh migration before seeding, it will clear all old data ?')) {
// Call the php artisan migrate:fresh using Artisan
$this->command->call('migrate:fresh');
$this->command->line("Database cleared.");
}
$this->call(GenreTableSeeder::class);
$this->call(UserFilmSeeder::class);
$this->call(CommentTableSeeder::class);
$this->command->info("Database seeded.");
// Re Guard model
Eloquent::reguard();
}
}
If you run php artisan db:seed
it will ask questions and seed the data accordingly.
#laravel #php