Laravel 10 填充数据

简单地说使用seeder进行数据填充,如果想批量填充,可以再结合Factory。
一、当已经创建了Model:Post,对应的migration核心部分为:

    public function up(): void
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->id();
            $table->string('slug')->unique();
            $table->string('title');
            $table->text('content');
            $table->softDeletes();
            $table->timestamp('published_at')->nullable();
            $table->timestamps();
        });
    }

现在先创建一个seeder:

php artisan make:seeder PostTabelSeeder

在database/seeders下面产生了PostTableSeeder.php,修改如下:

<?php

namespace Database\Seeders;

use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use App\Models\Post;

class PostTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     */
    public function run(): void
    {
         \App\Models\Post::factory()->create([
             'title' => '标题',
             'content' => '内容',
         ]);
    }
}

现在就可以直接填充一条数据了:

php artisan db:seed --class=PostTableSeeder

如果不想指定填充类,通过php artisan db:seed来填充Post,就需要修改DatabaseSeeder.php,来call你想指定的填充类(PostTableSeeder)

<?php

namespace Database\Seeders;

// use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use Database\Seeders\PostTableSeeder;
use Illuminate\Database\Eloquent\Model;

class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application's database.
     */
    public function run(): void
    {
        Model::unguard();
        $this->call(PostTableSeeder::class);
        Model::reguard();
    }
}

可以在DatabaseSeeder里添加多个Call

二、结合Factory来批量填充
当然,可以在PostTableSeeder里写循环语句来实现批量填充,但没有那么优雅。好的,现在创建一个Factory:

php artisan make:factory PostFactory

这样会在database/factories/下面多了一个PostFactory.php,修改如下:

<?php

namespace Database\Factories;

use Illuminate\Database\Eloquent\Factories\Factory;

/**
 * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Models\Post>
 */
class PostFactory extends Factory
{
    /**
     * Define the model's default state.
     *
     * @return array<string, mixed>
     */
    public function definition(): array
    {
        return [
            'title' => fake()->sentence(3, true),
            'content' => fake()->paragraphs(3,true),
            'published_at' => now(),
        ];
    }
}

对于fake的用法,请自行搜索学习,简单地说,fake可以方便地产生很多格式化的安全的数据

在此基础上,填充类的代码需要修改,也就是在PostTabelSeeder.php里不再直接生产数据,而且利用上面的工厂类:PostFactory。
PostTabelSeeder.php修改如下:

<?php

namespace Database\Seeders;

use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use App\Models\Post;

class PostTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     */
    public function run(): void
    {
        Post::factory(100)->create();
    }
}

直接填充100份。如果这时去填充,可能会失败,报XX字段默认不能为空,所以还要先修改Model:Post

<?php

namespace App\Models;

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

class Post extends Model
{
    use HasFactory;

    protected $dates = ['published_at'];

    public function setTitleAttribute($value)
    {
        $this->attributes['title'] = $value;
        if (! $this->exists) {
            $this->attributes['slug'] = Str::slug($value);
        }
    }

}

如果想在执行填充前对数据模型中某个属性进行相关操作,可以在相应的模型中定义set属性Attribute的方法
(setTitleAttribute)
现在填充就可以了:

php artisan db:seed

有一点一定要注意,正常情况下,不需要setTitleAttribute就可以正常填充数据的(当工厂里通过fake赋值的字段覆盖了所有没有默认值的字段时),但如果像本例子里面的Post里面有一个slug字段,值是通过title变换过来的,依赖于title,在工厂PostFacory里没有给slug通过fake给它赋值,而slug又没有默认值,所以如果不这样处理,直接填充数据就会报错,报slug没有默认值。所以必须要setTitleAttribute来提前处理slug。

本作品采用《CC 协议》,转载必须注明作者和本文链接
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!