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 协议》,转载必须注明作者和本文链接
推荐文章: