Реших го
Търсих много решение на този проблем и открих, че много други също са го изпитали. Ако имате нужда само от един елемент от другия край на вашата връзка, това е много просто .
Добавянето на „уникално ограничение за няколко колони“ е това, което направи това сложно. Единственото решение, което намерих, беше "Забравете ограничението на MySQL и просто обградете фабричното създаване с try-catch за PDO-изключения". Това изглеждаше като лошо решение, тъй като други PDOExceptions също биха били уловени и просто не се чувстваше „правилно“.
Решение
За да направя тази работа, разделих сеялките на ImageTableSeeder и ImageTextTableSeeder и и двете са много прави. И двете им команди за изпълнение изглеждат така:
public function run()
{
factory(App\Models\ImageText::class, 100)->create();
}
Магията се случва вътре в ImageTextFactory:
$factory->define(App\Models\ImageText::class, function (Faker\Generator $faker) {
// Pick an image to attach to
$image = App\Models\Image::inRandomOrder()->first();
$image instanceof App\Models\Image ? $imageId = $image->id : $imageId = null;
// Generate unique imageId-languageCode combination
$imageIdAndLanguageCode = $faker->unique()->regexify("/^$imageId-[a-z]{2}");
$languageCode = explode('-', $imageIdAndLanguageCode)[1];
return [
'image_id' => $imageId,
'language' => $languageCode,
'title' => $faker->word,
'text' => $faker->text,
];
});
Това е:
$imageIdAndLanguageCode = $faker->unique()->regexify("/^$imageId-[a-z]{2}");
Ние използваме imageId в regexify-израз и добавяме всичко, което също е включено в нашата уникална комбинация, разделена в този случай със знак '-'. Това ще генерира резултати като "841-en", "58-bz", "96-xx" и т.н., където imageId винаги е реално изображение в нашата база данни или нула.
Тъй като прилепваме уникалния маркер към езиковия код заедно с imageId, знаем, че комбинацията от image_id и languageCode ще бъде уникална . Точно това ни трябва!
Сега можем просто да извлечем създадения езиков код или каквото и да е друго уникално поле, което искаме да генерираме, с:
$languageCode = explode('-', $imageIdAndLanguageCode)[1];
Този подход има следните предимства:
- Няма нужда от улавяне на изключения
- Фабрики и сеялки могат да бъдат разделени за четливост
- Кодът е компактен
Недостатъкът тук е, че можете да генерирате само клавишни комбинации, където един от ключовете може да бъде изразен като регулярен израз. Доколкото това е възможно, това изглежда като добър подход за решаване на този проблем.