Mysql
 sql >> Base de données >  >> RDS >> Mysql

Laravel :ensemencer plusieurs colonnes uniques avec Faker

Je l'ai résolu

J'ai beaucoup cherché une solution à ce problème et j'ai constaté que beaucoup d'autres l'ont également vécu. Si vous n'avez besoin que d'un élément à l'autre bout de votre relation, c'est très simple .

L'ajout de la "restriction unique multi-colonnes" est ce qui a rendu cela compliqué. La seule solution que j'ai trouvée était "Oubliez la restriction MySQL et entourez simplement la création de l'usine avec un try-catch pour les exceptions PDO". Cela ressemblait à une mauvaise solution car d'autres PDOExceptions seraient également interceptées, et cela ne semblait tout simplement pas "correct".

Solution

Pour faire ce travail, j'ai divisé les seeders en ImageTableSeeder et ImageTextTableSeeder, et ils sont tous les deux très simples. Leurs commandes d'exécution ressemblent à ceci :

public function run()
{
    factory(App\Models\ImageText::class, 100)->create();
}

La magie opère à l'intérieur 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,
    ];
});

C'est ça :

$imageIdAndLanguageCode = $faker->unique()->regexify("/^$imageId-[a-z]{2}");

Nous utilisons l'imageId dans une expression regexify et ajoutons tout ce qui est également inclus dans notre combinaison unique, séparé dans ce cas par un caractère '-'. Cela générera des résultats comme "841-en", "58-bz", "96-xx" etc. où l'imageId est toujours une image réelle dans notre base de données, ou nulle.

Puisque nous collons la balise unique au code de langue avec l'imageId, nous savons que la combinaison de l'image_id et du languageCode sera unique . C'est exactement ce dont nous avons besoin !

Maintenant, nous pouvons simplement extraire le code de langue créé, ou tout autre champ unique que nous voulions générer, avec :

$languageCode = explode('-', $imageIdAndLanguageCode)[1];

Cette approche présente les avantages suivants :

  • Pas besoin d'intercepter les exceptions
  • Les usines et les semoirs peuvent être séparés pour plus de lisibilité
  • Le code est compact

L'inconvénient ici est que vous ne pouvez générer que des combinaisons de touches où l'une des clés peut être exprimée en regex. Tant que cela est possible, cela semble être une bonne approche pour résoudre ce problème.