Lo resolví
Busqué mucho una solución a este problema y descubrí que muchos otros también lo experimentaron. Si solo necesita un elemento en el otro extremo de su relación, es muy sencillo .
La adición de la "restricción única de múltiples columnas" es lo que hizo esto complicado. La única solución que encontré fue "Olvídese de la restricción de MySQL y simplemente rodee la creación de fábrica con una captura de prueba para las excepciones de PDO". Esto se sintió como una mala solución ya que otras PDOExceptions también quedarían atrapadas, y simplemente no se sentía "bien".
Solución
Para que esto funcione, dividí las sembradoras en ImageTableSeeder e ImageTextTableSeeder, y ambas son muy sencillas. Sus comandos de ejecución se ven así:
public function run()
{
factory(App\Models\ImageText::class, 100)->create();
}
La magia ocurre dentro de 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,
];
});
Esto es:
$imageIdAndLanguageCode = $faker->unique()->regexify("/^$imageId-[a-z]{2}");
Usamos imageId en una expresión regular y agregamos lo que sea que también esté incluido en nuestra combinación única, separados en este caso con un carácter '-'. Esto generará resultados como "841-en", "58-bz", "96-xx", etc. donde imageId es siempre una imagen real en nuestra base de datos, o nula.
Como pegamos la etiqueta única al código de idioma junto con el ID de imagen, sabemos que la combinación de ID_de_imagen y código de idioma será única . ¡Esto es exactamente lo que necesitamos!
Ahora podemos simplemente extraer el código de idioma creado, o cualquier otro campo único que quisiéramos generar, con:
$languageCode = explode('-', $imageIdAndLanguageCode)[1];
Este enfoque tiene las siguientes ventajas:
- No es necesario detectar excepciones
- Las fábricas y las sembradoras se pueden separar para facilitar la lectura
- El código es compacto
La desventaja aquí es que solo puede generar combinaciones de teclas donde una de las teclas se puede expresar como expresión regular. Siempre que sea posible, parece un buen enfoque para resolver este problema.