#Laravel Seeder Advance - Laravel Advance Topics Learning in a depth - Beyond the documentation
Categories - Laravel PHP Framework Tags - PHP Laravel   Maniruzzaman Akash   1 year ago   1408   0

#Laravel Seeder Advance - Laravel Advance Topics Learning in a depth - Beyond the documentation

What is Seeder in Laravel:

Seeder is a feature of Laravel Framework to Seed test data using Seeder classes. One can test his application easily with the help of Seeder classes. It's is in laravel's database/seeders directory. Whenever you want to add some dummy or fake or real common data to test or start your application, then you need the laravel seeder.

 

When Needs Laravel Seeder:

Here, I'll describe some scenerios, where we need seeder most.

  1. I have a blog, where I want to check my blog performance or blog look without real time but some static data. I'll use Seeder to store that static data.
  2. I have some categories fixed. How I add them first. Ok, I'll use Laravel Seeder.
  3. I want to check query performance after joining two or three tables. Ok, I'll use seeder to create three tables and get data from Seeder.
  4. I want to test Load balance of my application. Assume my application has post like Medium, the post could be 1 million. Let's Add 1 million data and test
  5. And so on many scenarios to use Laravel's Seeder.

 

How to Create Seeder

Seeder will be created at database/seeders directory. Let's run a command inside the Laravel project - to create a seeder. We want to seed some users for our website.

php artisan make:seeder UserSeeder

So, a new file will be auto generated inside database/seeders/UserSeeder.php file.

 

Inside database/seeders/UserSeeder.php file, let's put some code to create a random user.

<?php

namespace Database\Seeders;

use App\Models\User;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;

class UserSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        User::insert([
            'name' => Str::random(10),
            'email' => Str::random(10).'@gmail.com',
            'password' => Hash::make('password'),
        ]);
    }
}

So, it'll insert a user with some random data using Larave's Str class.

 

Call this UserSeeder from Database Seeder:

in app/databases/seeders/DatabaseSeeder.php file

<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application's database.
     *
     * @return void
     */
    public function run()
    {
        $this->call([
            UserSeeder::class,
        ]);
    }
}

 

How to Run Seeder

To run Laravel Seeder, there are some Artisan commands available.

 

To run all of the seeders - db:seed

php artisan db:seed

 

To run single file seeder - Only seed UserSeeder, --class=UserSeeder

php artisan db:seed --class=UserSeeder

 

To run seeder with database refresh:

php artisan migrate:fresh --seed

It'll drop all the tables and re-run all of your migrations. This is used to regenerate the whole site's data in the database.

 

Force Run Seeder in production mode:

php artisan db:seed --force

 

Laravel Seeder with Model Factory

To run Laravel Seeder with the factory dataset. 

Laravel has a feature called - Model factory. Which can generate fake data for testing and so on. With the help of Factory and Faker package, we can generate fake data easily.

Let's have a look also at Faker Package - https://github.com/fzaninotto/Faker

Faker is by default installed in Laravel. So, you don't have to worry about that.

 

let's see, how we'll make the factory system. Processes - 

  1. We'll create Two Model - Post and Category
  2. We'll create migrations for them with a Proper relationship
  3. We'll migrate them
  4. We'll make Factory for Post and Category model.
  5. We'll make CategorySeeder
  6. We'll make PostSeeder
  7. We'll dump 20 Categories on our database
  8. We'll Dump 20K posts on our server

 

Create Models with migration -

 

We'll create Two Model - Post and Category

// Create Category Model with migration
php artisan make:model Category -m

// Create Post Model with migration
php artisan make:model Post -m

Now, in app/Models folder, two files will be created - Category.php, Post.php.

in database/migrations folder, two files will also be created - 

  • 2021_07_01_211827_create_categories_table.php
  • 2021_07_03_211325_create_posts_table.php

 

Modify Category model's migration - 

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateCategoriesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('categories', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('categories');
    }
}

Creates only a name field column.

 

Update Post model's migration file - 

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreatePostsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->id();
            $table->string('title');
            $table->text('description')->nullable();

            $table->foreignId('user_id')
                ->constrained()
                ->onUpdate('cascade')
                ->onDelete('cascade');

            $table->foreignId('category_id')
                ->constrained()
                ->onUpdate('cascade')
                ->onDelete('cascade');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('posts');
    }
}

 Added actually newly 4 columns - title, description, user_id, category_id.

 

Modify Models File ?

No, we don't need any modification in model file. and you can check by default HasFactory trait is used in the model. So, we can access all of it's properties in the Post model.

 

app/Models/Post.php

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    use HasFactory;
}

 

app/Models/Category.php

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Category extends Model
{
    use HasFactory;
}

 

Create Factory for Post

Inside database/factories/ folder, create a file called - PostFactory.php, Name would be like this [model]Factory.php.

<?php

namespace Database\Factories;

use App\Models\Category;
use App\Models\Post;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;

class PostFactory extends Factory
{
    /**
     * The name of the factory's corresponding model.
     *
     * @var string
     */
    protected $model = Post::class;

    /**
     * Define the model's default state.
     *
     * @return array
     */
    public function definition()
    {
        $categoryIds = Category::pluck('id')->toArray();
        $userIds     = User::pluck('id')->toArray();

        return [
            'title'       => $this->faker->sentence(),
            'description' => $this->faker->text(),
            'user_id'     => $userIds[array_rand($userIds)],
            'category_id' => $categoryIds[array_rand($categoryIds)]
        ];
    }
}

We've created the following factory dataset - 

  1. title - A fake sentence as title
  2. description - A fake text as description
  3. user_id - Take random user ids from the users table
  4. category_id - Take random category ids from the categories table

 

Create Factory for Category

Inside database/factories/ folder, create a file called - CategoryFactory.php

<?php

namespace Database\Factories;

use App\Models\Category;
use Illuminate\Database\Eloquent\Factories\Factory;

class CategoryFactory extends Factory
{
    /**
     * The name of the factory's corresponding model.
     *
     * @var string
     */
    protected $model = Category::class;

    /**
     * Define the model's default state.
     *
     * @return array
     */
    public function definition()
    {
        return [
            'name' => $this->faker->sentence(3)
        ];
    }
}

Here - definition for category name - A sentence of 3 words.

 

Make the Real Seeder - PostSeeder

 

Create two seeder for our project - PostSeeder and CategorySeeder

// Category Seeder
php artisan make:seeder CategorySeeder

// Post Seeder
php artisan make:seeder PostSeeder

 

Now, in app/databases/seeders/PostSeeder.php

<?php

namespace Database\Seeders;

use App\Models\Post;
use Illuminate\Database\Seeder;

class PostSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        Post::factory()
            ->count(20000) // 20K posts
            ->create();
    }
}

We've created a PostSeeder with factory(), which will create 20K posts following the factory definition.

 

Now, in app/databases/seeders/CategorySeeder.php

<?php

namespace Database\Seeders;

use App\Models\Category;
use Illuminate\Database\Seeder;

class CategorySeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        Category::factory()
            ->count(20) // 20 Categories
            ->create();
    }
}

We've created 20 categories of the creatable seeders.

 

We can also change the UserSeeder to generate dummy Users - 

in app/databases/seeders/UserSeeder.php file

<?php

namespace Database\Seeders;

use App\Models\User;
use Illuminate\Database\Seeder;

class UserSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        User::factory()
            ->count(200) // 200 Users
            ->create();
    }
}

 

Add Seeder Classes in DatabaseSeeder.php file - 

<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application's database.
     *
     * @return void
     */
    public function run()
    {
        $this->call([
            UserSeeder::class,
            CategorySeeder::class,
            PostSeeder::class
        ]);
    }
}

 

Let's run our Seeder with refreshing the database - 

php artisan migrate:fresh --seed

 

That's it, after running this artisan command - 200 Users, 20 Categories and 20000 Posts will be created.

 

And hope so - You've got almost all points of Laravel seeder.

 

Download Codes From Github Repository -

https://github.com/ManiruzzamanAkash/Laravel-Advanced-Topics/tree/seeder-example