I have a unique constraint in my database for two columns.
$table->unique(array("table_a_id", "table_b_id"));
Now I use Faker in a seeder class to fill in this pivot table:
$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
]);
}
However this creates duplicates and the seeding fails due to SQL error.
How do I make sure I don't try to insert duplicates?
Instead of using faker, use the collection's random
method:
$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],
]);
}
Adjust this according to your needs.
For example, this might be what you really want:
$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,
]);
}
}
Whatever it is, play with it yourself. No need for faker here.
You can use this:
$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: This may not work if from the begining TableA and TableB datas are inconsistents (meaning it is not possible to form 20 uniques couples from those data )
$unique = $faker->unique()->regexify('[0-4][0-9][0-4][0-9]');
The code above will result in a string composed of two numbers between 0 and 49 that never repeats. Now you can break into two and seed your database securely.
$firstId = ltrim(substr($unique, 0, 2), '0') + 1;
$secondId = ltrim(substr($unique, 2, 2), '0') + 1;
The two numbers can be the same in a string, but a string will always be unique. Don't forget to add one for each of the parts because we don't want (and we can't) to seed our database with zeros.