3. Seeds and Fabrics. Заполнение базы тестовыми данными

31 Мая 2020 22:17 (Редактировано: 03 Июня 2020 22:57)

Сиды и фабрики - инструменты для наполнения базы тестовыми данными. Фабрики выполняют функцию генерации каких-то данных (случайных или нет), а сиды - запускают фабрики и вносят данные в базу.

Фабрики

Фабрики находятся в директории project.loc/database/factories/

Создание фабрики

1. Фабрика для пользователей уже присутствует по умолчанию. В ней оставляем все как есть.

2. Создаем фабрику для постов BlogPostFactory. Пишем в терминал: 

php artisan make:factory BlogPostFactory --model="App\Models\BlogPost"

После этого будет создан файл BlogPostFactory.php в директории factories/.

Логика фабрики

Наполняем файл, недавносозданный файл BlogPostFactory.php кодом: 

<?php

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

use App\Models\BlogPost;
use Faker\Generator as Faker;
use Illuminate\Support\Str;

$factory->define(BlogPost::class, function (Faker $faker) {
    $title = $faker->sentence(rand(3, 8), true);
    $txt = $faker->realText(rand(1000, 4000));
    $isPublished = rand(1, 5) > 1;

    $createdAt = $faker->dateTimeBetween('-3 months', '-2 months');

    $data = [
        'category_id'  => rand(1, 10),
        'user_id'      => (rand(1, 5) == 5) ? 1 : 2,
        'title'        => $title,
        'slug'         => Str::of($title)->slug(),
        'excerpt'      => $faker->text(rand(40, 100)),
        'content_raw'  => $txt,
        'content_html' => $txt,
        'is_published' => $isPublished,
        'published_at' => $isPublished ? $faker->dateTimeBetween('-2 months', '-1 days') : null,
        'created_at'   => $createdAt,
        'updated_at'   => $createdAt
    ];


    return $data;
});

Сиды

Сиды хранятся в директории project.loc/database/seeds.

Создание сидов

Запускаем команды в консоли:

php artisan make:seeder UsersTableSeeder
php artisan make:seeder BlogCategoriesTableSeeder

Таким образом, в директории seeds создадутся два файла с заранее подготовленным для рабты кодом: BlogCategoriesTableSeeder.php и UsersTableSeeder.php.

Все, что будет находитсья в методе run будет выполнено при запуске сидов.

Логика сидов

1. Заполняем файл категорий BlogCategoriesTableSeeder.php:

<?php

use Illuminate\Database\Seeder;

class BlogCategoriesTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        $categories = [];

        $cName = 'Без категории';
        $categories[] = [
            'title' => $cName,
            'slug' => Str::of($cName)->slug(),
            'parent_id' => 0,
        ];

        for($i = 0; $i <= 10; $i++) {
            $cName = 'Категория #' . $i;
            $parentId = ($i > 4) ? rand(1, 4) : 1;

            $categories[] = [
                'title' => $cName,
                'slug' => Str::of($cName)->slug(),
                'parent_id' => $parentId,
            ];
        }

        \DB::table('blog_categories')->insert($categories);
    }
}

Примечание. В старых версиях laravel 5.х для создания правильных URL используется функция str_slug. В более поздних версиях заменили на статический метод Str::slug(). Также доступен метод of(), который создает объект Stringable, который также содержит метод slug(), но он ссылается на Str:slug(), поэтому, скорее всего, разницы в использовании Str::of() или Str::slug() нет.

Примечание. Чтобы работали методы Str, надо добавить пространство имен в начале use Illuminate\Support\Str;

2. Заполянем файл пользователей UsersTableSeeder.php

<?php

use Illuminate\Database\Seeder;

class UsersTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        $data = [
            [
                'name'     => 'Автор неизвестен',
                'email'    => 'author_unknown@g.g',
                'password' => bcrypt(Str::random(16))
            ],
            [
                'name'     => 'Автор',
                'email'    => 'author@g.g',
                'password' => bcrypt('123123')
            ]
        ];

        DB::table('users')->insert($data);
    }
}

Примечание. Здесь испоьзуем Str::random() вместо str_random

3. Заполняем файл DatabaseSeeder.php. Это основной файл сидов, который мы будем запускать командой в терминале. Он поочередно запустит созданные нами сиды и фабрику. Пишем код:

<?php

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application's database.
     *
     * @return void
     */
    public function run()
    {
        $this->call(UsersTableSeeder::class);
        $this->call(BlogCategoriesTableSeeder::class);
        factory(\App\Models\BlogPost::class, 100)->create();
    }
}

Таким образом, создано все необходимое для наполнения базы данных готовыми тестовыми данными. Можно приступать к запуску сидов.

Запуск сидов

Запускать сиды можно в разных режимах. Это основные:

php artisan db:seed #Залить все данные
php artisan db:seed --class=UsersTableSeeder #Залить данные только отдельной таблицы
php artisan migrate:refresh --seed #Откатить все данные, заново мигрировать базы и наполнить данными

Делаем ради теста php artisan migrate:refresh --seed и получаем в базу: 2 юзера, 11 категорий, 100 постов!