Search code examples
phplaravelfactorylaravel-seeding

Laravel 8: Unable to Query Table during Seeding Using Factory


I have a seeder:

class DatabaseSeeder extends Seeder
{
    public function run(): void
    {
        $this->call([
            ArticlesTableSeeder::class,
        ]);
    }
}

The seeder itself:

class ArticlesTableSeeder extends Seeder
{
    public function run(): void
    {
        Article::factory()->count(10000)->create();
    }
}

My Article model has a slug column and as you may guess every time I set a slug using mutator (setSlugAttribute($value)) I have to query articles table to see if the given slug exists and if it does I have to generate new one and append -1 at the end, eg:

  • illo-et-et-quibusdam - first post
  • illo-et-et-quibusdam-2 - second post

and so on…

This all works as expected but not during the seeding, because I see that if I seed 10k of records, they don't appear on my table until all 10k are done. So when my mutator tries to query table, it doesn't see the same slug (assuming faker will generate the same one) and then after 6-7k I get:

SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'illo-et-et-quibusdam' for key 'articles.articles_slug_unique' (SQL: insert into `articles`

Can I turn transactions off during seeding or is there anything I can do to fix this issue?


Solution

  • The only workaround I was about to think about (that actually works) is defining quantity of records to seed, not by calling count() method on the factory, but outside of it in a loop.

    So instead of seeding 10k of articles like:

    Article::factory()->count(10000)->create();
    

    I have to:

    for ($i = 0; $i < 10000; $i++) {
        Article::factory()->count(1)->create();
    }
    

    I can obviously drop ->count(1).

    With this I can ⌘+R in Sequel Ace or any other client and see how the number of records grow with each refresh. This means that records are there and slug lookup works correctly, therefore avoiding dupes on unique slug index.

    Please let me know if you find a better solution.