laravel 模型工厂种子从现有生成

laravel model factory seed generate from existing

我正在尝试使用外键为 table 播种,但我一直坚持如何告诉模型从已经存在的内容中随机提取值。

模型工厂

$factory->define(App\Vendor::class, function(Faker\Generator $faker) {
    return [
        'name' => $faker->company,
    ];
});

$factory->define(App\Device::class, function(Faker\Generator $faker) {
    return [
        'vendor' => ,
        'name' => $faker->company,
        'mac_address' => $faker->macAddress,
    ];
});

种子

VendorTableSeeder

public function run()
{
    factory(App\Vendor::class, 150)->create();
}

DeviceTableSeeder

public function run()
{
    factory(App\Device::class, 50)->create();
}

DataSeeder

$this->call(VendorTableSeeder::class);
$this->call(DeviceTableSeeder::class);

我在设备 table 之前播种供应商 table,并希望从现有供应商中随机填充一个供应商 ID。

'vendor' => 'factory::App\Vendor'

但我得到

SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: foreign key constraint fails

看起来插入正在尝试将 factory::App\Vendor 作为供应商列的字符串插入。我正在尝试弄清楚如何从现有供应商那里获取它。

同时从 VendorTableSeeder.

播种它们

您是否需要没有供应商的设备?还是没有设备的供应商?如果没有,那么这是最好的选择。相关表应该放在一起。

更好的例子是学校。学校是主要的种子,对于每所学校,您还可以播种一名校长、几名教师和 100 名学生。如果您一次将它们全部播种,就可以消除对外键或排序的担忧。

factory(App\Vendor::class, 150)
    ->create()
    ->each(function (App\Vendor $vendor) {
        $vendor->devices()->save(
            factory(App\Device::class)->make()
        );

        // For some randomness
        $vendor->devices()->save(
            factory(App\Device::class, rand(0, 4))->make()
        );
    });

如果您确实希望灵活地分别为它们播种,那么您还有其他几个选择。您可以在设备工厂内部拉取随机供应商。

$factory->define(App\Device::class, function(Faker\Generator $faker) {

    // Grab a random vendor
    $vendor = App\Vendor::orderByRaw('RAND()')->first();

    // Or create a new vendor
    $vendor = factory(App\Vendor::class)->create();

    return [
        'vendor_id'   => $vendor->id,
        'name'        => $faker->company,
        'mac_address' => $faker->macAddress,
    ];
});

或者您可以传递与工厂生成的属性合并的额外属性。

// $vendor is a Vendor object

factory(App\Device::class, 50)->create([
    'vendor_id' => $vendor->id,
]);

我是这样处理我的地址的,我这样做了 10% 的时间它会创建一个新地址,否则使用随机地址。

// Grab a random address
$address = App\Address::orderByRaw('RAND()')->first();

// 10% that we will generate a new address
if ($faker->boolean(10) || !$address)
{
    $address = factory(App\Address::class)->create();
}

基本上我会获取一个随机地址,如果它存在,$faker->boolean(10) 将有 10% 的机会 return true 并且它会生成一个新地址。但是如果没有地址($address == false)我们总是生成一个新地址。

这是使用 random() 方法生成工厂的简单方法

$factory->define(App\Device::class, function(Faker\Generator $faker) {
    return [
        // another way to, Get any random row from existing records
        'vendor_id' => App\Vendor::all()->random()->user_id,
        'name'        => $faker->company,
        'mac_address' => $faker->macAddress,
    ];
});