Laravel : 如何使用工厂以特定模式为模型播种?
Laravel : How do I use factories to seed models in a specific pattern?
我有一个存储个人地址的模型。
一个人可以有多个地址,满足以下条件:
- 必须有一个地址标记为永久地址。
- 必须有一个地址标记为当前地址。
- 一个地址可以同时标记为永久地址和当前地址。
- 地址既不能是永久地址也不能是当前地址。
我正在尝试使用工厂为数据库播种。
个人地址工厂:
$factory->define(PersonAddress::class, function (Faker $faker) {
return [
'Address' => $faker->buildingNumber . ',' . $faker->streetName . ',' . $faker->streetAddress,
'Landmark' => $faker->optional()->words(3, true),
'CityID' => App\Entities\City::inRandomOrder()->first()->CityID,
'PostalCode' => $faker->postcode,
'IsPermanent' => ???
'IsCurrent' => ???
];
});
播种者:
public function run() {
$no_of_persons = (int)$this->command->ask('How many persons do you want to create?', 10);
$this->command->info("Seeding {$no_of_persons} persons");
$persons = factory(App\Entities\Person::class, $no_of_persons)->create();
$this->command->info('Persons Created!');
// Creating addresses for persons
$this->command->info('Creating Addresses for persons');
$persons->each(
function ($person) {
factory(App\Entities\PersonAddress::class, rand(1, 5))->create(['PersonID' => $person->PersonID]);
});
$this->command->info('Addresses Created!');
}
如何解决这个问题?
我认为简单的方法是首先强制使用一个当前永久的地址,然后是随机种子。
use App\Entities\PersonAddress;
// ...
$persons->each(function ($person) {
factory(PersonAddress::class)->create(['PersonId' => $person->PersonID, 'permanent' => true, 'current' => true]);
factory(PersonAddress::class, rand(0, 5))->create(['PersonId' => $person->PersonID]);
});
或者另一种方法是像你一样播种,然后检查数据库中是否有永久和当前,如果没有,则创建一个。
$persons->each(function ($person) {
factory(PersonAddress::class, rand(1, 5))->create(['PersonID' => $person->PersonID]);
$permanentCount = PersonAddress::where('PersonID', $person->PersonId)->where('permanent', true)->count();
$currentCount = PersonAddress::where('PersonID', $person->PersonId)->where('current', true)->count();
if (! $permanentCount || ! $currentCount) {
factory(PersonAddress::class, rand(1, 5))->create([
'PersonID' => $person->PersonID,
'permanent' => $permanentCount < 1,
'current' => $currentCount < 1
]);
}
});
单独定义工厂类型
$factory->define(PersonAddress::class, function (Faker $faker) {
return [
'Address' => $faker->buildingNumber . ',' . $faker->streetName . ',' . $faker->streetAddress,
'Landmark' => $faker->optional()->words(3, true),
'CityID' => App\Entities\City::inRandomOrder()->first()->CityID,
'PostalCode' => $faker->postcode,
'IsPermanent' => false,
'IsCurrent' => false,
];
});
$factory->defineAs(PersonAddress::class, 'permanent', function (Faker $faker) {
$address = $factory->raw(PersonAddress::class);
return array_merge($address, ['IsPermanent' => true, 'IsCurrent' => false]);
});
$factory->defineAs(PersonAddress::class, 'current', function (Faker $faker) {
$address = $factory->raw(PersonAddress::class);
return array_merge($address, ['IsPermanent' => false, 'IsCurrent' => true]);
});
$factory->defineAs(PersonAddress::class, 'permanent_and_current', function (Faker $faker) {
$address = $factory->raw(PersonAddress::class);
return array_merge($address, ['IsPermanent' => true, 'IsCurrent' => true]);
});
并使用它们随机生成
public function run() {
$no_of_persons = (int)$this->command->ask('How many persons do you want to create?', 10);
$this->command->info("Seeding {$no_of_persons} persons");
$persons = factory(App\Entities\Person::class, $no_of_persons)->create();
$this->command->info('Persons Created!');
// Creating addresses for persons
$this->command->info('Creating Addresses for persons');
$persons->each(
function ($person) {
if (rand(1, 2) == 1) {
// make different current and permanent addresses
factory(App\Entities\PersonAddress::class, 'permanent', rand(1, 5))->create(['PersonID' => $person->PersonID]);
factory(App\Entities\PersonAddress::class, 'current', rand(1, 5))->create(['PersonID' => $person->PersonID]);
} else {
// make same address as permanent and current
factory(App\Entities\PersonAddress::class, 'permanent_and_current', rand(1, 5))->create(['PersonID' => $person->PersonID]);
}
// make some random addresses
factory(App\Entities\PersonAddress::class, rand(0, 3))->create(['PersonID' => $person->PersonID]);
});
$this->command->info('Addresses Created!');
}
回答我自己的问题:
根据 回答的提示,我更新了代码以使用工厂状态,这是最终代码。
个人地址工厂:
$factory->define(PersonAddress::class, function (Faker $faker) {
return [
'Address' => $faker->buildingNumber . ',' . $faker->streetName . ',' . $faker->streetAddress,
'Landmark' => $faker->optional()->words(3, true),
'CityID' => App\Entities\City::inRandomOrder()->first()->CityID,
'PostalCode' => $faker->postcode,
'IsPermanent' => '0',
'IsCurrent' => '0',
];
});
$factory->state(PersonAddress::class, 'permanent', ['IsPermanent' => '1']);
$factory->state(PersonAddress::class, 'current', ['IsCurrent' => '1']);
$factory->state(PersonAddress::class, 'permanent_and_current', ['IsPermanent' => '1', 'IsCurrent' => '1']);
播种者:
public function run() {
$no_of_persons = (int)$this->command->ask('How many persons do you want to create?', 10);
$this->command->info("Seeding {$no_of_persons} persons");
$persons = factory(App\Entities\Person::class, $no_of_persons)->create();
$this->command->info('Persons Created!');
// Creating addresses for persons
$this->command->info('Creating Addresses for persons');
$persons->each(
function ($person) {
if (rand(1, 2) == 1) {
factory(App\Entities\PersonAddress::class)->state('permanent')->create(['PersonID' => $person->PersonID]);
factory(App\Entities\PersonAddress::class)->state('current')->create(['PersonID' => $person->PersonID]);
}
else {
factory(App\Entities\PersonAddress::class)->state('permanent_and_current')->create(['PersonID' => $person->PersonID]);
}
factory(App\Entities\PersonAddress::class, rand(0, 3))->create(['PersonID' => $person->PersonID]);
});
$this->command->info('Addresses Created!');
}
我有一个存储个人地址的模型。 一个人可以有多个地址,满足以下条件:
- 必须有一个地址标记为永久地址。
- 必须有一个地址标记为当前地址。
- 一个地址可以同时标记为永久地址和当前地址。
- 地址既不能是永久地址也不能是当前地址。
我正在尝试使用工厂为数据库播种。
个人地址工厂:
$factory->define(PersonAddress::class, function (Faker $faker) {
return [
'Address' => $faker->buildingNumber . ',' . $faker->streetName . ',' . $faker->streetAddress,
'Landmark' => $faker->optional()->words(3, true),
'CityID' => App\Entities\City::inRandomOrder()->first()->CityID,
'PostalCode' => $faker->postcode,
'IsPermanent' => ???
'IsCurrent' => ???
];
});
播种者:
public function run() {
$no_of_persons = (int)$this->command->ask('How many persons do you want to create?', 10);
$this->command->info("Seeding {$no_of_persons} persons");
$persons = factory(App\Entities\Person::class, $no_of_persons)->create();
$this->command->info('Persons Created!');
// Creating addresses for persons
$this->command->info('Creating Addresses for persons');
$persons->each(
function ($person) {
factory(App\Entities\PersonAddress::class, rand(1, 5))->create(['PersonID' => $person->PersonID]);
});
$this->command->info('Addresses Created!');
}
如何解决这个问题?
我认为简单的方法是首先强制使用一个当前永久的地址,然后是随机种子。
use App\Entities\PersonAddress;
// ...
$persons->each(function ($person) {
factory(PersonAddress::class)->create(['PersonId' => $person->PersonID, 'permanent' => true, 'current' => true]);
factory(PersonAddress::class, rand(0, 5))->create(['PersonId' => $person->PersonID]);
});
或者另一种方法是像你一样播种,然后检查数据库中是否有永久和当前,如果没有,则创建一个。
$persons->each(function ($person) {
factory(PersonAddress::class, rand(1, 5))->create(['PersonID' => $person->PersonID]);
$permanentCount = PersonAddress::where('PersonID', $person->PersonId)->where('permanent', true)->count();
$currentCount = PersonAddress::where('PersonID', $person->PersonId)->where('current', true)->count();
if (! $permanentCount || ! $currentCount) {
factory(PersonAddress::class, rand(1, 5))->create([
'PersonID' => $person->PersonID,
'permanent' => $permanentCount < 1,
'current' => $currentCount < 1
]);
}
});
单独定义工厂类型
$factory->define(PersonAddress::class, function (Faker $faker) {
return [
'Address' => $faker->buildingNumber . ',' . $faker->streetName . ',' . $faker->streetAddress,
'Landmark' => $faker->optional()->words(3, true),
'CityID' => App\Entities\City::inRandomOrder()->first()->CityID,
'PostalCode' => $faker->postcode,
'IsPermanent' => false,
'IsCurrent' => false,
];
});
$factory->defineAs(PersonAddress::class, 'permanent', function (Faker $faker) {
$address = $factory->raw(PersonAddress::class);
return array_merge($address, ['IsPermanent' => true, 'IsCurrent' => false]);
});
$factory->defineAs(PersonAddress::class, 'current', function (Faker $faker) {
$address = $factory->raw(PersonAddress::class);
return array_merge($address, ['IsPermanent' => false, 'IsCurrent' => true]);
});
$factory->defineAs(PersonAddress::class, 'permanent_and_current', function (Faker $faker) {
$address = $factory->raw(PersonAddress::class);
return array_merge($address, ['IsPermanent' => true, 'IsCurrent' => true]);
});
并使用它们随机生成
public function run() {
$no_of_persons = (int)$this->command->ask('How many persons do you want to create?', 10);
$this->command->info("Seeding {$no_of_persons} persons");
$persons = factory(App\Entities\Person::class, $no_of_persons)->create();
$this->command->info('Persons Created!');
// Creating addresses for persons
$this->command->info('Creating Addresses for persons');
$persons->each(
function ($person) {
if (rand(1, 2) == 1) {
// make different current and permanent addresses
factory(App\Entities\PersonAddress::class, 'permanent', rand(1, 5))->create(['PersonID' => $person->PersonID]);
factory(App\Entities\PersonAddress::class, 'current', rand(1, 5))->create(['PersonID' => $person->PersonID]);
} else {
// make same address as permanent and current
factory(App\Entities\PersonAddress::class, 'permanent_and_current', rand(1, 5))->create(['PersonID' => $person->PersonID]);
}
// make some random addresses
factory(App\Entities\PersonAddress::class, rand(0, 3))->create(['PersonID' => $person->PersonID]);
});
$this->command->info('Addresses Created!');
}
回答我自己的问题:
根据
个人地址工厂:
$factory->define(PersonAddress::class, function (Faker $faker) {
return [
'Address' => $faker->buildingNumber . ',' . $faker->streetName . ',' . $faker->streetAddress,
'Landmark' => $faker->optional()->words(3, true),
'CityID' => App\Entities\City::inRandomOrder()->first()->CityID,
'PostalCode' => $faker->postcode,
'IsPermanent' => '0',
'IsCurrent' => '0',
];
});
$factory->state(PersonAddress::class, 'permanent', ['IsPermanent' => '1']);
$factory->state(PersonAddress::class, 'current', ['IsCurrent' => '1']);
$factory->state(PersonAddress::class, 'permanent_and_current', ['IsPermanent' => '1', 'IsCurrent' => '1']);
播种者:
public function run() {
$no_of_persons = (int)$this->command->ask('How many persons do you want to create?', 10);
$this->command->info("Seeding {$no_of_persons} persons");
$persons = factory(App\Entities\Person::class, $no_of_persons)->create();
$this->command->info('Persons Created!');
// Creating addresses for persons
$this->command->info('Creating Addresses for persons');
$persons->each(
function ($person) {
if (rand(1, 2) == 1) {
factory(App\Entities\PersonAddress::class)->state('permanent')->create(['PersonID' => $person->PersonID]);
factory(App\Entities\PersonAddress::class)->state('current')->create(['PersonID' => $person->PersonID]);
}
else {
factory(App\Entities\PersonAddress::class)->state('permanent_and_current')->create(['PersonID' => $person->PersonID]);
}
factory(App\Entities\PersonAddress::class, rand(0, 3))->create(['PersonID' => $person->PersonID]);
});
$this->command->info('Addresses Created!');
}