Mysql
 sql >> Database >  >> RDS >> Mysql

Laravel:semina di più colonne uniche con Faker

Ho risolto

Ho cercato molto una soluzione a questo problema e ho scoperto che anche molti altri l'hanno sperimentato. Se hai bisogno di un solo elemento all'altro capo della tua relazione, è molto semplice .

L'aggiunta della "restrizione unica a più colonne" è ciò che ha reso tutto ciò complicato. L'unica soluzione che ho trovato è stata "Dimentica la restrizione MySQL e circonda semplicemente la creazione di fabbrica con un try-catch per le eccezioni PDO". Sembrava una cattiva soluzione poiché anche altre PDOException sarebbero state rilevate e semplicemente non sembrava "giusto".

Soluzione

Per fare questo lavoro ho diviso i seeders in ImageTableSeeder e ImageTextTableSeeder, e sono entrambi molto semplici. I loro comandi di esecuzione hanno entrambi il seguente aspetto:

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

La magia avviene all'interno di 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,
    ];
});

Eccolo:

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

Usiamo l'imageId in un'espressione regexify e aggiungiamo tutto ciò che è anche incluso nella nostra combinazione univoca, separato in questo caso con un carattere '-'. Questo genererà risultati come "841-en", "58-bz", "96-xx" ecc. dove l'imageId è sempre un'immagine reale nel nostro database, o null.

Dal momento che fissiamo il tag univoco al codice della lingua insieme all'imageId, sappiamo che la combinazione di image_id e languageCode sarà unica . Questo è esattamente ciò di cui abbiamo bisogno!

Ora possiamo semplicemente estrarre il codice della lingua creato, o qualsiasi altro campo univoco che vogliamo generare, con:

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

Questo approccio presenta i seguenti vantaggi:

  • Non c'è bisogno di catturare le eccezioni
  • Le fabbriche e le seminatrici possono essere separate per la leggibilità
  • Il codice è compatto

Lo svantaggio qui è che puoi generare solo combinazioni di tasti in cui una delle chiavi può essere espressa come regex. Finché è possibile, questo sembra un buon approccio per risolvere questo problema.