laravel进阶--3 数据库填充器及模型工厂

蔚丰
2023-12-01

生成填充器

要生成一个填充器,可以通过 Artisan 命令 make:seeder。所有框架生成的填充器都位于 database/seeds 目录:

php artisan make:seeder StudentsTableSeeder

编辑填充器

<?php

use Illuminate\Database\Seeder;
use App\Http\Models\Student;
class StudentsTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        //
        //手动填充
        // DB::table('students')->insert([
        //     'name'=>str_random(10),
        //     'age'=>rand(10,30),
        //     'sex'=>rand(10,30),
        // ]);
        
        //模型工厂批量填充

        //make() 生成假数据
       // $student = factory(App\Http\Models\Student::class)->make();
        //$student = factory(Student::class,5)->make();

        //create() 生成假数据并填充到数据库
        $student = factory(Student::class,5)->create();

        //var_dump($student);exit();

    }
}

调用其他填充器

 

在 DatabaseSeeder 类中,你可以使用 call 方法执行其他填充类,使用 call 方法允许你将数据库填充分解成多个文件,这样单个填充器类就不会变得无比巨大,只需简单将你想要运行的填充器类名传递过去即可:

/**
 * 运行数据库填充
 *
 * @return void
 */
public function run(){
    $this->call(UsersTableSeeder::class);
    $this->call(PostsTableSeeder::class);
    $this->call(CommentsTableSeeder::class);
}

运行填充器

编写好填充器类之后,需要通过 dump-autoload 命令重新生成 Composer 的自动加载器:

composer dump-autoload

运行之后可以使用 Artisan 命令 db:seed 来填充数据库。默认情况下,db:seed 命令运行 DatabaseSeeder 类,不过,你也可以使用 --class 选项来指定你想要运行的独立的填充器类:

//运行所有填充器
php artisan db:seed
//运行指定填充器
php artisan db:seed --class=StudentsTableSeeder

运行之后可能报错,是因为Student模型类没有设置

<?php

namespace App\Http\Models;

use Illuminate\Database\Eloquent\Model;

class Student extends Model
{
    //
    /**
     * 关联到模型的数据表
     *
     * @var string
     */
    protected $table = 'students';

    /**
     * 定义主键
     *
     * @var string
     */
    protected $primaryKey = 'id';

    /**
     * 模型日期列的存储格式
     * $dateFormat 属性。该属性决定日期被如何存储到数据库中,以及模型被序列化为数组或 JSON 时日期的格式
     * $dateFormat 可以接受的值和 php 中 date () 函数第一个参数可以接受的值一样。
     *  U 的意思就是我们平常说的时间戳 (10 位到秒)
     * Y m d H i s 都可用
     * @var string
     */
   protected $dateFormat = 'U';

    /**
     * 不能被批量赋值的属性
     * 黑名单
     * @var array
     */
   // protected $guarded = ['price'];
   protected $guarded = [];//所有属性都可赋值
}

模型工厂

生成模型工厂

模型工厂可用于快速填充数据表。要创建一个模型工厂,可以使用 Artisan 命令 make:factory:

php artisan make:factory StudentFactory

新创建的工厂类位于 database/factories 目录下。

--model 选项可用于指示模型工厂对应的模型类。该选项通过给定的模型名称预填充生成的工厂类:

php artisan make:factory StudentFactory --model=Student

编辑模型工厂

PHP 库 Faker : https://github.com/fzaninotto/Faker

在闭包中,作为工厂定义,我们返回该模型上所有属性默认测试值。该闭包接收 PHP 库 Faker 实例,从而允许你方便地为测试生成多种类型的随机数据

<?php

use Faker\Generator as Faker;
use App\Http\Models\Student;
$factory->define(Student::class, function (Faker $faker) {
    return [
        //
        'name' => $faker->word(),
        'age' => $faker->numberBetween(10,50),
        'sex' => $faker->randomElement(array(10,20,30)),
        'created_at' => $faker->unixTime(),
        'updated_at' => $faker->unixTime(),
    ];
});

使用工厂

创建模型

 

定义好工厂后,可以在测试或数据库填充文件中通过全局的 factory 方法使用它们来生成模型实例,所以,让我们看一些创建模型的例子,首先,我们使用 make 方法,该方法创建模型但不将其保存到数据库:

public function testDatabase(){
    $user = factory(App\User::class)->make();
    // 用户模型测试...
}

//还可以创建多个模型集合或者创建给定类型的模型:

// 创建3个 App\User 实例...
$users = factory(App\User::class, 3)->make();

 

应用状态

还可以应用任意状态到模型,如果你想要应用多个状态转化到模型,需要指定每个你想要应用的状态名:

$users = factory(App\User::class, 5)->states('deliquent')->make();
$users = factory(App\User::class, 5)->states('premium', 'deliquent')->make();

覆盖属性

如果你想要覆盖模型中的某些默认值,可以传递数组值到 make 方法,只有指定值才会被替换,剩下值保持工厂指定的默认值不变:

$user = factory(App\User::class)->make([
    'name' => 'Abigail',
]);

持久化模型

create 方法不仅能创建模型实例,还可以使用 Eloquent 的 save 方法将它们保存到数据库

public function testDatabase()
{
    // 创建单个 App\User 实例...
    $user = factory(App\User::class)->create();

    // 创建3个 App\User 实例...
    $users = factory(App\User::class, 3)->create();

    // 在测试中使用模型...
}

你可以通过传递数组到 create 方法覆盖模型上的属性:
$user = factory(App\User::class)->create([
    'name' => 'Abigail',
]);

关联关系

 

在本例中,我们添加一个关联到创建的模型,使用 create 方法创建多个模型的时候,会返回一个 Eloquent 集合实例,从而允许你使用集合提供的所有方法,例如 each:

$users = factory(App\User::class, 3)
           ->create()
           ->each(function($u) {
                $u->posts()->save(factory(App\Post::class)->make());
            });

关联关系 & 属性闭包

 

还可以使用工厂中的闭包属性添加关联关系到模型,例如,如果你想要在创建 Post 的时候创建一个新的 User 实例,可以这么做:

$factory->define(App\Post::class, function ($faker) {
    return [
        'title' => $faker->title,
        'content' => $faker->paragraph,
        'user_id' => function () {
            return factory(App\User::class)->create()->id;
        }
    ];
});

这些闭包还接收包含它们的工厂属性数组:

$factory->define(App\Post::class, function ($faker) {
    return [
        'title' => $faker->title,
        'content' => $faker->paragraph,
        'user_id' => function () {
            return factory(App\User::class)->create()->id;
        },
        'user_type' => function (array $post) {
            return App\User::find($post['user_id'])->type;
        }
    ];
});

 

 

 

 类似资料: