title: Laravel: Seeding multiple unique columns with Faker
body: <p><strong>Introduction</strong></p>
  
  <p>What up folks, I got a question about model factories and multiple unique columns:</p>
  
  <p><strong>Background</strong></p>
  
  <p>I have a model named Image. This model has language support stored in a separate model, <strong>ImageText</strong>. <strong>ImageText</strong> has an <strong>image_id</strong> column, a language column and a text column.</p>
  
  <p><strong>ImageText</strong> has a constraint in <strong>MySQL</strong> that the combination <strong>image_id</strong> and language has to be unique.</p>
  
  <pre><code>class CreateImageTextsTable extends Migration
  {
  
      public function up()
      {
          Schema::create('image_texts', function ($table) {
  
              ...
  
              $table-&gt;unique(['image_id', 'language']);
  
              ...
  
          });
      }
  
      ...
  </code></pre>
  
  <p>Now, I want each <strong>Image</strong> to have several <strong>ImageText</strong> models after seeding is done. This is easy with model factories and this seeder:</p>
  
  <pre><code>factory(App\Models\Image::class, 100)-&gt;create()-&gt;each(function ($image) {
      $max = rand(0, 10);
      for ($i = 0; $i &lt; $max; $i++) {
          $image-&gt;imageTexts()-&gt;save(factory(App\Models\ImageText::class)-&gt;create());
      }
  });
  </code></pre>
  
  <p><strong>Problem</strong></p>
  
  <p>However, when seeding this using model factories and faker, you are often left with this message:</p>
  
  <pre><code>[PDOException]                                                                                                                 
  SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '76-gn' for key 'image_texts_image_id_language_unique'
  </code></pre>
  
  <p>This is because at some point, inside that for loop, the faker will random the same languageCode twice for an image, breaking the unique constraint for ['image_id', 'language'].</p>
  
  <p>You can update your <strong>ImageTextFactory</strong> to say this:</p>
  
  <pre><code>$factory-&gt;define(App\Models\ImageText::class, function (Faker\Generator $faker) {
  
      return [
          'language' =&gt; $faker-&gt;unique()-&gt;languageCode,
          'title' =&gt; $faker-&gt;word,
          'text' =&gt; $faker-&gt;text,
      ];
  });
  </code></pre>
  
  <p>But then, you instead get the problem that the faker will run out of languageCodes after enough imageTexts have been created.</p>
  
  <p><strong>Current solution</strong></p>
  
  <p>This is currently solved by having two different factories for the ImageText, where one resets the unique counter for languageCodes and the seeder calls the factory which resets te unique counter before entering the for loop to create further ImageTexts. But this is code duplication, and there should be a better way to solve this.</p>
  
  <p><strong>The question</strong></p>
  
  <p>Is there a way to send the model you are saving on into the factory? If so, I could have a check inside the factory to see if the current Image has any ImageTexts attached already and if it doesn't, reset the unique counter for languageCodes. My goal would be something like this:</p>
  
  <pre><code>$factory-&gt;define(App\Models\ImageText::class, function (Faker\Generator $faker) {
  
      $firstImageText = empty($image-&gt;imageTexts());
  
      return [
          'language' =&gt; $faker-&gt;unique($firstImageText)-&gt;languageCode,
          'title' =&gt; $faker-&gt;word,
          'text' =&gt; $faker-&gt;text,
      ];
  });
  </code></pre>
  
  <p>Which of course currently gives:</p>
  
  <pre><code>[ErrorException]           
  Undefined variable: image
  </code></pre>
  
  <p>Is it possible to achieve this somehow?</p>