SkillAgentSearch skills...

Populate

Populate your database with a supercharged, continuable seeder

Install / Use

/learn @Laragear/Populate
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

Populate

Latest Version on Packagist Latest stable test run Codecov coverage Maintainability Sonarcloud Status Laravel Octane Compatibility

Populate your database with a supercharged, continuable seeder.

use Laragear\Populate\Seeder;

class UserSeeder extends Seeder
{
    public function seedNormalUsers()
    {
        //
    }
    
    public function seedBannedUsers()
    {
        
    }
}

Become a sponsor

Your support allows me to keep this package free, up-to-date and maintainable.

Requirements

  • PHP 8.3 or later
  • Laravel 12 or later

Installation

You can install the package via Composer.

composer require laragear/populate

How does this work?

Laravel's Seeding system is very antique and basic. This library supercharges the seeding system of Laravel to make it more friendly to develop and run.

By hijacking the default Seeder with a better one, we can supercharge the seed system to allow per-step seeding, skipping and continuable seeding, without sacrificing on its normal features, and keeping compatibility with classic seeding classes.

Set up

You may create a super-seeder using make:super-seeder Artisan command, and the name of the seeder.

php artisan make:super-seeder UserSeeder

You will receive a Super Seeder with single seed() method, and two others one that will execute before and after.

namespace Database\Seeders:

use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Laragear\Populate\Seeder;

class UserSeeder extends Seeder
{
    /**
     * Run logic before executing the seed steps.
     */
    public function before(): void
    {
        // if (false) {
        //     $this->skip();
        // }
    }

    /**
     * Populate the database with records.
     */
    public function seed(): void
    {
        //
    }

    /**
     * Run logic after executing the seed steps.
     */
    public function after(): void
    {
        //
    }
}

[!TIP]

If you already created your application seeders, replace the Illuminate\Database\Seeder import to Laragear\Populate\Seeder.

namespace Database\Seeders;

// use Illuminate\Database\Seeder;
use Laragear\Populate\Seeder;

class UserSeeder extends Seeder
{
    //..
}

If you want to change the seeder stub, you may publish it through the vendor:publish Artisan command under the stub tag.

php artisan vendor:publish --provider=Laragear\Populate\PopulateServiceProvider --tag=stubs

Usage

Instead of using the run() method in your seeder, this library's seeders use the concept of Seed Steps. A Seed Step is just a public method that starts with seed, or uses the Laragear\Populate\Attributes\SeedStep attribute, named to briefly describe the records that are being inserted.

The container instantiates the Seeder and also calls each Seed Step, so you can use Dependency Injection as arguments anywhere you require.

namespace Database\Seeders;

use Database\Factories\UserFactory;
use Laragear\Populate\Attributes\SeedStep;
use Laragear\Populate\Seeder;
use App\TicketGenerator;

class UserSeeder extends Seeder
{
    public function __construct(protected TicketGenerator $ticket)
    {
        // ...
    }

    public function seedNormalUsers(UserFactory $users)
    {
        $users->count(5)->create(['ticket' => $this->ticket->generate()]);
    }

    public function seedVipUsers(UserFactory $users)
    {
        $users->vip()->count(3)->create();
    }
    
    #[SeedStep]
    public function bannedUsers(UserFactory $users)
    {
        $users->banned()->count(2)->create(['ticket' => $this->ticket->generate()]);
    }
}

For convenience, a Seed Step will persist all records if these return a Model Factory, a Collection of Models or a single Model.

use Database\Factories\UserFactory;

public function seedNormalUsers(UserFactory $users)
{
    return $users->count(5);
}

When the seeder is called, each Seed Step will be output to the console like this:

php artisan db:seed

INFO Seeding database.

Database\Seeders\UserSeeder ...................................... RUNNING
~ Seed normal users ................................................. DONE
~ Seed banned users ................................................. DONE
Database\Seeders\UserSeeder .................................. 107 ms DONE

Custom Seed Step naming

Each Seed Step is described in the console output as First word capitalized, so a Seed Step function called seedVipUsers will be displayed as Seed vip users. If you total control, the SeedStep attribute accepts an argument to change the output description.

use Laragear\Populate\Attributes\SeedStep;

#[SeedStep(as: 'Seed non-authorized users')]
public function bannedUsers(UserFactory $users)
{
    $users->banned()->count(2)->create(['ticket' => $this->ticket->generate()]);
}

That will output the step as named, verbatim:

php artisan db:seed

INFO Seeding database.

Database\Seeders\UserSeeder ...................................... RUNNING
~ Seed normal users ................................................. DONE
~ Seed non-authorized users ......................................... DONE
Database\Seeders\UserSeeder .................................. 107 ms DONE

Calling with arguments

When calling other seeders inside a Seed Step, you may use the usual $this->call() method and its variants. Classic seeders will execute their run() method as always if the method exists.

When doing calling a Super Seeder, you may set an array of arguments for each seed task by issuing their name as a key and the arguments as an array. This can be great when a seeder contains a Seed Steps that would require parameters to properly populate records on the database.

use Database\Factories\UserFactory;
use Database\Factories\CommentFactory;
use Laragear\Populate\Seeder;

class UserSeeder extends Seeder
{
    // ...
  
    public function seedMutedUsers(UserFactory $factory)
    {
        $users = $factory->muted()->create(3);
        
        $this->call(CommentSeeder::class, [
            'seedModeratedComment' => ['users' => $users],
        ]);
    }
}

class CommentSeeder extends Seeder
{
    public function seedModeratedComment(CommentFactory $comments, $users)
    {
        foreach ($users as $user) {
            $comments->for($user)->moderated()->create();
        }
    }
}

Before & After

When calling a seeder, you may implement the before() and after() methods to run logic before the Seed Steps are executed, and after all are done with, respectively. As with Seed Steps, these are called through the Service Container.

use Illuminate\Contracts\Config\Repository;use Illuminate\Contracts\Routing\UrlGenerator;
use Laragear\Populate\Seeder;

class CommentSeeder extends Seeder
{
    public function before(UrlGenerator $url)
    {
        // ...
    }
    
    public function after(Repository $config)
    {
        // ...
    }
}

On Error

For better control on Seed Steps that returns errors, you may implement the onError() method that receives the offending exception. It's great to use for cleaning artifacts before stopping the seeding operation.

use Laragear\Populate\Seeder;

class CommentSeeder extends Seeder
{
    public function onError($exception)
    {
        // ...
    }
}

You may also return or throw another exception to replace the previous exception.

public function onError($exception)
{
    return new RuntimeException('The seeder failed', previous: $exception);
}

Skipping

Laragear's Seeders support skipping either a Seed Step or the whole Seeder. Both are done through the skip() method.

Skipping a Seed Step

To skip a Seed Step, you only need to call the skip() method inside it.

use App\Models\User;
use Database\Factories\UserFactory;

public function seedBannedUsers(UserFactory $user)
{
    if (User::query()->banned()->exists()) {
        $this->skip();
    }
    
    // ...
}

It will output something like this:

php artisan db:seed

INFO Seeding database.

Database\Seeders\UserSeeder ...................................... RUNNING
~ Seed normal users ................................................. DONE
~ Seed non-authorized users ...................................... SKIPPED
Database\Seeders\UserSeeder .................................. 107 ms DONE

The skip() method supports using a reason for skip which will be displayed in the console output.

use App\Models\User;

if (User::query()->banned()->exists()) {
    $this->skip('There are already banned users in the database');
}
Database\Seeders\UserSeeder ...................................... RUNNING
~ Seed normal users ................................................. DONE
~ Seed non-authorized users ...................................... SKIPPED
  There are already banned users in the dat
View on GitHub
GitHub Stars86
CategoryData
Updated22d ago
Forks1

Languages

PHP

Security Score

95/100

Audited on Mar 8, 2026

No findings