我的数据库中有两列的唯一约束。
$table->unique(array("table_a_id", "table_b_id"));
现在我在种子类中使用Faker来填充这个数据透视表:
$tableAIds = TableA::all()->lists("id")->toArray();
$tableBIds = TableB::all()->lists("id")->toArray();
foreach(range(1, 20) as $index) {
$tableAId = $faker->randomElement($tableAIds);
$tableBId = $faker->randomElement($tableBIds);
DB::table("table_a_table_b_pivot")->insert([
"table_a_id" => $tableAId,
"table_b_id" => $tableBId
]);
}
但是,这会创建重复项,并且由于SQL错误而导致种子设定失败。
如何确保不尝试插入重复项?
您可以使用这个:
$tableAIds = TableA::all()->lists("id")->toArray();
$tableBIds = TableB::all()->lists("id")->toArray();
foreach (range(1, 20) as $index) {
repeat:
$tableAId = $faker->randomElement($tableAIds);
$tableBId = $faker->randomElement($tableBIds);
try {
DB::table("table_a_table_b_pivot")->insert([
"table_a_id" => $tableAId,
"table_b_id" => $tableBId,
]);
} catch ('Illuminate'Database'QueryException $e) {
//look for integrity violation exception (23000)
if($e->errorInfo[0]==23000)
goto repeat;
}
}
Ps:如果从一开始表A和表B的数据不一致(这意味着不可能从这些数据中形成20个uniques偶(,
$unique = $faker->unique()->regexify('[0-4][0-9][0-4][0-9]');
上面的代码将产生一个由0到49之间的两个数字组成的字符串,该字符串从不重复。现在,您可以将数据库分成两部分,并安全地为数据库播种。
$firstId = ltrim(substr($unique, 0, 2), '0') + 1;
$secondId = ltrim(substr($unique, 2, 2), '0') + 1;
字符串中的两个数字可以相同,但字符串始终是唯一的。不要忘记为每个部分添加一个,因为我们不想(也不能(用零作为数据库的种子。
不要使用faker,而是使用集合的random
方法:
$tableAIds = TableA::all()->lists('id')->random(20);
$tableBIds = TableB::all()->lists('id')->random(20);
foreach(range(0, 19) as $index) {
DB::table("table_a_table_b_pivot")->insert([
"table_a_id" => $tableAIds[$index],
"table_b_id" => $tableBIds[$index],
]);
}
根据您的需要进行调整。
例如,这可能是您真正想要的:
$tableAIds = TableA::all()->lists('id');
$tableBIds = TableB::all()->lists('id');
foreach ($tableAIds->random(5) as $tableAId) {
foreach ($tableBIds->random(2) as $tableBId) {
DB::table("table_a_table_b_pivot")->insert([
"table_a_id" => $tableAId,
"table_b_id" => $tableBId,
]);
}
}
不管是什么,你自己玩吧。这里不需要faker。