Laravel Version: 7.x(7.24)

Seeding is one of my favorite tools that helps my development tremendously. This is how you could insert some(I mean whatever amount you want) records to database. Using Faker library to randomize the value, you could specify how far the randomness of your record values are. Check what Faker Provider could do and there’s additional Faker Provider Collection to step up your faking game.

  • Just clone a project from the cloud? migrate then seed the database
  • Think that your database values is confusing to manage? empty then reinsert data
  • Make a new table but too lazy to populate it? just run Seeder
  • Has migration with many tables and its a mess to seed the data? Use Seeder

All with a simple CLI command.

php artisan db:seed

Or for more granular control

php artisan db:seed --class=SomeTableSeeder

Interested? carry on reading!

Installation

Faker is shipped default with Laravel & Lumen, But you need to install the Faker Provider Collection. If you are not sure what is provided, once again do check their providers, its helpful.

composer require mbezhanov/faker-provider-collection
# just in case for migration
composer require doctrine/dbal

That will do.

Make an Empty Database

Make a database of your choice, then update you .env database detail to match your database setting.

DB_CONNECTION=mysql
DB_HOST=192.168.10.10
DB_PORT=3306
DB_DATABASE=lara-seeding-tutorial
DB_USERNAME=homestead
DB_PASSWORD=secret

Here I use MySQL 8 for the database called lara-seeding-tutorial in a Laravel Homestead which has ip of 192.168.10.10 and port 3306. The MySQL username is homestead and the password is secret

Update yours according to your database credential.

Create Table

We will use laravel’s migration tools to create the table, so in the future we could run this migration script to create the tables instead of running an sql file dump. Faster and easier.

We will create a migration file that create a table called products. Use this command to generate that file.

php artisan make:migration create_products_table
php artisan make:migration create_categories_table
php artisan make:migration create_transactions_table

Which will create a new files

/database/migrations/[current_date]_[somenumber]_create_products_table.php
/database/migrations/[current_date]_[somenumber]_create_categories_table.php
/database/migrations/[current_date]_[somenumber]_create_transactions_table.php

This is the current file content and its modidification highlighted:

This file will create table called products with columns named:

<?php
# /database/migrations/2020_09_07_112121_create_categories_table.php

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

class CreateProductsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('products', function (Blueprint $table) {
            $table->id();
+            $table->string('name');
+            $table->text('description');
+            $table->integer('price');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('products');
    }
}
<?php
# /database/migrations/2020_09_07_112121_create_categories_table.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');
    }
}
<?php
# /database/migrations/020_09_07_112121_create_categories_table.php

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

class CreateTransactionsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('transactions', function (Blueprint $table) {
            $table->id();
+           $table->foreignId('product_id')->nullable();
+           $table->unsignedBigInteger('price');
+           $table->integer('quantity');
            $table->timestamps();

+           $table->foreign('product_id')->references('id')->on('products')->onDelete('set null');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
+       Schema::table('transactions', function (Blueprint $table){
+           $table->dropForeign('transactions_product_id_foreign');
+       });
        Schema::dropIfExists('transactions');
    }
}

Let’s create a simple table for product, we will have product name, description, and price on the table

Next step is test this migration file to be able to create table & de-create it a.k.a drop it when necessary.

To make the migration take effect, use this script

php artisan migrate

Which will result in this(the user related & jobs tables are built in from laravel install)

vagrant@homestead:~/code/lara-seeding-tutorial$ php artisan migrate
Migration table created successfully.
Migrating: 2014_10_12_000000_create_users_table
Migrated:  2014_10_12_000000_create_users_table (0.1 seconds)
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated:  2014_10_12_100000_create_password_resets_table (0.09 seconds)
Migrating: 2019_08_19_000000_create_failed_jobs_table
Migrated:  2019_08_19_000000_create_failed_jobs_table (0.06 seconds)
Migrating: 2020_09_06_160325_create_products_table
Migrated:  2020_09_06_160325_create_products_table (0.05 seconds)

Congratulation, from 2 last line, your table is migrated. You could check it in your database, there will be a new table called products there, along with some other.

Now we check if the table could be deleted when you reset the migration by run this command:

php artisan migrate:rollback --step=1

This command will reset the last migrate command described in the down() function of your last file(s) affected by the migration. In our case it will delete tables name users, password_resets, failed_jobs, and products table.

Create Models

Run this to create model class for products table.

php artisan make:model Models/Product

The result will be located at app/Models/Product. This class will seek table called products

Define Your Columns Value

Now that we could create the table structure with ease, it is time for us to define what kind of values those tables columns have. We will define this values in a class called Factory Class. In laravel you could create this class through command line

php artisan make:factory ProductFactory

This will make a new file /database/factories/ProductFactory.php with following content:

<?php

/** @var \Illuminate\Database\Eloquent\Factory $factory */

use App\Model;
use Faker\Generator as Faker;

$factory->define(Model::class, function (Faker $faker) {
    return [
        //
    ];
});

Update it to look like this

<?php

/** @var \Illuminate\Database\Eloquent\Factory $factory */

- use App\Model;
+ use App\Models\Product;
+ use Bezhanov\Faker\ProviderCollectionHelper;
  use Faker\Generator as Faker;

- $factory->define(Model::class, function (Faker $faker) {
+ $factory->define(Product::class, function (Faker $faker) {
+     ProviderCollectionHelper::addAllProvidersTo($faker);
      return [
-         //
+         'name' => $faker->productName,
+         'description' => $faker->realText(),
+         'price' => $faker->numberBetween(200, 999999),
      ];
  });

This ProductFactory file will describe the value of your column

ProviderCollectionHelper::addAllProvidersTo($faker);

Will add additional categories of things to choose from.

        'name' => $faker->productName,
        'description' => $faker->realText(),
        'price' => $faker->numberBetween(200, 999999),

productName will make random product name that we could still relate

realText() will make random sentence

numberBetween(200, 9000) will make random number between 200 to 9000

Your First Seeder

This is the class which you would run to insert your database records. This class could contains the way you would insert your records to database.

There are more than one way to insert records to your table(s).

If you have a kind of fixed types table, maybe a list of genders, or a few status choices, You could use DB::insert() instead of the Factory file like above. That would be simpler.

But when you have a table with many columns and records coming from user input(meaning this will be random within certain criteria), the Factory file is your friend. Let your computer randomise those input, inserting hundreds or thousands of records will be a breeze.

Now let’s make a Seeder class. My way of seeding tables is make a class named after the table name with Seeder ending. For example we wanted to make a Seeder for products table , I just call it ProductSeeder. Laravel has the command to make the class

php artian make:seeder ProductSeeder

You will found the newly generated class in /database/seeds/ProductSeeder.php. Let’s take a look inside:

<?php

use Illuminate\Database\Seeder;

class ProductSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        //
    }
}

We just need to call the factory that we have describe.

  <?php
+ use App\Models\Product;
  use Illuminate\Database\Seeder;

  class ProductSeeder extends Seeder
  {
      /**
       * Run the database seeds.
       *
       * @return void
       */
      public function run()
      {
-          //
+          factory(Product::class, 137)->create();
      }
  }

That is it. We will insert a 137 records on products table.

to run this, use this command

php artisan db:seed --class=ProductSeeder

And when you check the database records of products table, 137 new records is there.

inserted product records

Tadaaa. The products table has records now, exacly 137 records.

if you are not certain, run this command to reset your database structure

php artisan migrate:rollback

This command will revert back your database to only one table, migrations table

Then run this command to create those tables

php artisan migrate

which will migrate all your tables, you will see the products tables is back. But there’s no database records there. Run the seeding command again to fill it

php artisan db:seed --class=ProductSeeder

Refresh your database, and you will see records on your products table with different values, but still inside the criteria

Conclusion

In this article I demonstrate to you how migration & seeding work using laravel. This combination could be used in other framework too using different tools. This is a simple example.