Jag löste det
Jag letade mycket efter en lösning på detta problem och upptäckte att många andra också upplevde det. Om du bara behöver ett element i andra änden av din relation, är det väldigt enkelt .
Tillägget av den "unika begränsningen för flera kolumner" är det som gjorde detta komplicerat. Den enda lösningen jag hittade var "Glöm MySQL-begränsningen och omge bara fabriksskapandet med en try-catch för PDO-undantag". Detta kändes som en dålig lösning eftersom andra PDO-undantag också skulle fångas, och det kändes helt enkelt inte "rätt".
Lösning
För att få detta att fungera delade jag såmaskinerna till ImageTableSeeder och ImageTextTableSeeder, och de är båda väldigt raka fram. Deras körkommandon ser båda ut så här:
public function run()
{
factory(App\Models\ImageText::class, 100)->create();
}
Magin händer i 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,
];
});
Det här är det:
$imageIdAndLanguageCode = $faker->unique()->regexify("/^$imageId-[a-z]{2}");
Vi använder imageId i ett regexify-uttryck och lägger till det som också ingår i vår unika kombination, separerat i det här fallet med ett "-"-tecken. Detta kommer att generera resultat som "841-en", "58-bz", "96-xx" etc. där imageId alltid är en riktig bild i vår databas, eller null.
Eftersom vi fäster den unika taggen på språkkoden tillsammans med imageId, vet vi att kombinationen av image_id och languageCode kommer att vara unik . Det är precis vad vi behöver!
Nu kan vi helt enkelt extrahera den skapade språkkoden, eller vilket annat unikt fält vi ville generera, med:
$languageCode = explode('-', $imageIdAndLanguageCode)[1];
Detta tillvägagångssätt har följande fördelar:
- Du behöver inte fånga undantag
- Fabriker och såmaskiner kan separeras för läsbarhet
- Koden är kompakt
Nackdelen här är att du bara kan generera tangentkombinationer där en av nycklarna kan uttryckas som regex. Så länge det är möjligt verkar detta vara ett bra sätt att lösa det här problemet.