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.

Writing Seeders and Model Factories

Table of Contents

  • Pratical Example
  • Generating Model and Migration
  • Write Migration and Model Factory
  • Generating Seeder
  • Write Database Seeder
  • Conclusion

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.

Pratical Example

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 .

Generating Model and Migration

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

Write Migration and Model Factory

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)),
      ];
});

Generating Seeder

Write Genre Seeder

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!');

    }

Write User and Film Seeder

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));
    }

Write Comment Seeder

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));
    }

Write Database Seeder

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();

    }
}

Conclusion

If you run php artisan db:seed it will ask questions and seed the data accordingly.

#laravel #php

Make your Laravel Seeder Using Model Factories
3 Likes341.85 GEEK