TALL Stack

Creating Your First Blog With TALL – Part Four

Table of Content

Welcome back to today's episode. You learned everything about setting up your database: creating models, different approaches to running database queries, and running migrations in the last episode. This episode builds on that by teaching you how to create database factories and seed our database tables with sample data we can use for our blog.

You should be able to learn the following at the end of this tutorial:

  • What model factories are.
  • How to create and write model factories.
  • What database seeders are.
  • How to create and write database seeders.
  • How to run database seeders in order to seed our blog's database with some sample data.

Model Factories

Model factories in Laravel allow you to generate dummy/fake data using the Faker PHP library. The Faker library allows generating random data by specifying various attributes. With factories you define fake data to be generated for each attribute/column of your model. This not only saves you time of manually inserting database records, but enables you to save thousands of records in your database within seconds.

Creating Factories

Factories are created using the Laravel make:factory Artisan command, like so:

php artisan make:factory PostFactory

This creates the PostFactory factory in the database/factories folder with no model specified. To specify a model the factory belongs to, you can append the --model option to the above command. You can also create a factory when creating a new model with -f option and that model will eventually be created when the factory is run, as we did in the previous tutorial.

If you open the database/factories/PostFactory.php file you should notice the factory class definition is similar to this:


<?php

namespace Database\Factories;

use App\Models\Post;
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()
    {
        return [
            //
        ];
    }
}

A Laravel factory basically extends the base Factory class and defines two important members: a $model the factory will be creating and a definition method that defines the values to be applied when the factory is executed. The $model property will be automatically filled when you create the factory with the make:factory command by specifying the --model option and when you specify the -f option when creating a model.

Writing Factories

Though our factory is created, we'll have to tell Laravel how we want our data to be generated when this factory is run. To do that, we have to define each attribute/column of the Post model/post table and its corresponding value as an associative array of key-value pairs in the definition method of our factory.

The base Laravel Factory class has a Faker instance and so each factory has access to this Faker instance. You generate values for each of your columns using this Faker instance. So, the definition for our Post model's attributes will look like below:

// tall-blog/database/factories/PostFactory.php
...
...
...
    /**
     * Define the model's default state.
     *
     * @return array
     */
    public function definition()
    {
        return [
            'category' => $this->faker->text(100),
            'body' => $this->faker->paragraphs(15, true),
            'title' => $this->faker->sentence(15),
            'excerpt' => $this->faker->sentences(3, true),
            'featured_image' => "post.png",
            'published_date' => $this->faker->date(),
            'user_id' => 1,
        ];
    }

You notice that we've "hard-coded" some values such as the user_id and the featured_image fields. This is because auto-generating these values will not be the best since they depend on other factors. We've also left out the is_published field since we provided a default false value for it and want a post to stay unpublished until we decide to publish it.

One thing we'd want to add to our factory is a published state. This can be used to modify the default value of the is_published column(which, by default, is false) whenever we want to make a particular post as published. Add this method at the end of the PostFactory class to do that:

// tall-blog/database/factories/PostFactory.php
...
...
... 
/**
     * Indicates the post is published.
     *
     * @return \Illuminate\Database\Eloquent\Factories\Factory
     */
    public function published()
    {
        return $this->state(function (array $attributes) {
            return [
                'is_published' => true,
                'published_date' => now(),
            ];
        });
    }

You see that this method uses the state method provided by the base factory class, which accepts a closure containing the attributes we defined for this factory in the definition method as an argument and returns the attributes to modify. Here we're just changing the is_published column to true and providing the current date-time as the published date.

Using Factories

After creating and defining your factories, the next thing is to use them to create models. This can be achieved by using the factory method provided by the HasFactory trait we talked about in the previous episode like so:

//Creates a post without persisting to database
$post = Post::factory()->make();

// Same as above, but creates five(5) posts
$post = Post::factory()->count(5)->make();

// Same as above, but sets the published state to true
$post = Post::factory()->count(5)->published()->make();

//Creates a post and persists it to database
$post = Post::factory()->create();

// Same as persisting, but creates five(5) posts
$post = Post::factory()->count(5)->create();

// Same as persisting, but sets the published state to true
$post = Post::factory()->count(5)->published()->create();

Database Seeders

While model factories let you create sample data for your models, database seeders actually insert these data into the database, though seeders don't necessarily have to depend on factories to insert data. This means you can either use factories to seed data into your database or manually utilize Eloquent and the Query Builder to do so.

Seeders are placed in the database/seeders directory of your Laravel installation and, by default, contain a single run method - which is called when the db:seed command is executed. By default, Laravel creates a DatabaseSeeder class for you out of the box. You can use this class to run other seeders by providing them to the call method. This allows you to properly organize and arrange your seeders in any order you desire and also helps you run many seeders at once.

Creating Database Seeders

Just like other features of the Laravel framework, database seeders are created by running Artisan commands. You execute the make:seeder Artisan command and provide the name of the seeder to create, like so:

php artisan make:seeder PostSeeder

Writing Database Seeders

As I already mentioned above, seeders, by default, contain a single run method that is executed when the db:seed command is run. In the run method you insert your data by manually running Eloquent queries or by using factories. We're using the latter for this tutorial.

To insert data, we're going to make use of the PostFactory we created in the previous sections. Within the run method put this:

// tall-blog/database/seeders/PostSeeder.php
...
...
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        Post::factory()
                ->count(20)
                ->published()
                ->create();
    }
...
...

We're creating 20 records of the Post model into our database whilst specifying that each post's state must be published, as opposed to the default unpublished behavior.

The last thing we want to do is open the DatabaseSeeder class and add the PostSeeder class to the call method's arguments in the run method:

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

Though we could just run the PostSeeder without adding it here, doing it this way keeps your seeders organized and decoupled and can be run from a single central point.

Running the Seeder

Now that our seeder and factory are defined, we can proceed to seed our database with sample data. As pointed out already, seeders are run using the db:seed command and optionally providing the --class option, which is used to specify the seeder class we want to run:

php artisan db:seed

I didn't provide the --class option because Laravel runs the DatabaseSeeder class by default if it is not provided. Running the above will produce an output such as this:

kamil@kamil-sc650:~/Projects/Web/tall-blog$ php artisan db:seed
Seeding: Database\Seeders\PostSeeder
Seeded: Database\Seeders\PostSeeder (3,633.28ms)
Database seeding completed successfully.

Check your database to see the posts table filled with 20 posts.

This brings us to the end of the fourth episode of Creating Your First Blog With TALL tutorial series. Our next episode will teach you how to create and write your first Livewire components. See you then.

chevron_left
chevron_right

Leave a comment

Your email address will not be published. Required fields are marked *

Comment
Name
Email
Website