25

I would like to pass an argument as to define how many records I want to create during database seeding, without having to edit the factory manually.

I have tried different variations on php artisan db:seed --class=UsersTableSeeder [using different args here]

I can't seem to find any documentation, so I don't know if that functionally exists. Does something like that exist?

class UsersTableSeeder extends Seeder
{
    public $limit = null;

    public function __construct($limit = 1) {
        $this->limit = $limit;
    }

    public function run()
    {
      echo $this->limit;
    }
}
user3741469
  • 103
  • 3
user-44651
  • 3,924
  • 6
  • 41
  • 87

7 Answers7

35

There is no way to directly specify an argument.

If you want to specify a parameter via the command line, you could use an environment variable.

class UsersTableSeeder extends Seeder
{
    public function run()
    {
        $limit = env('SEEDER_LIMIT', 1);

        echo $this->limit;
    }
}

Call like this:

SEEDER_LIMIT=10 php artisan db:seed --class=UsersTableSeeder
patricus
  • 59,488
  • 15
  • 143
  • 145
  • 3
    @TimLewis In this case, it's using an environment variable set from the shell environment, not from the `.env` file. Even if this value is defined in the `.env` file, any variables defined in the shell environment take precedence, so you can override values defined in the `.env`. Where you have to be careful, though, is when you cache your config. When the config is cached, the `.env` file is not loaded. This is why it is highly discouraged to use the `env()` function outside of the config files. I used it here for simplicity and since seeders are normally used in dev envs w/o cached configs. – patricus Nov 27 '19 at 20:23
  • @TimLewis Also because the default value is hard coded in the code (not set in the `.env` file), and because any change to the default value would require the environment variable to be set in the shell, which the `env()` function will read regardless of a cached config. – patricus Nov 27 '19 at 20:24
  • Yeah, of course, totally agree with everything, I just didn't realize you could set transient `env` (I guess not `.env`) variables via the command line like that. Seems pretty useful for 1-off things like this. Cheers for the information! – Tim Lewis Nov 27 '19 at 20:25
  • 1
    @TimLewis No problem. Glad I could help. :) – patricus Nov 27 '19 at 20:26
20

You can set it up this way:

public function run($count = 1)

And then you can pass the argument this way:

$this->call(ClientSeeder::class, false, ['count' => 500]);
oknate
  • 1,068
  • 10
  • 14
16

From what I know there's no such thing as parameters for seeders, but you could implement it yourself. You could create a new command which accepts parameters and calls a seeder programmatically with those additional parameters.

Something like this should do the trick:

use Illuminate\Database\Seeder;

class UsersTableSeeder extends Seeder
{

    public function run(int $limit)
    {
        echo $limit;
        // Seed some stuff
    }
}

namespace App\Console\Commands;

use Illuminate\Console\Command;
use UsersTableSeeder;

class SeedCommand extends Command
{
    protected $signature = 'app:seed {limit}';

    public function handle(UsersTableSeeder $seeder)
    {
        $limit = $this->argument('limit');
        $seeder->run($limit);
    }
}
PtrTon
  • 3,705
  • 2
  • 14
  • 24
  • 1
    I was just in the process of writing this as a comment, which it probably should be. While this is correct, it doesn't quite answer the question. If you provide an example (syntax for creating the command, example of params being passed to the command, generating a new instance of the seeder and further passing the arguments to that, then actually calling `run()`, etc. etc.), then it would answer it, but this question might also be too broad. – Tim Lewis Nov 27 '19 at 19:54
  • 1
    Hi Tim, I like that we both came up with the same answer. I do not have the time to put this into an actual code example. Feel free to add your own answer with code. So we can mark that as accepted – PtrTon Nov 27 '19 at 19:56
  • That's just it, I don't really have the time either; it's more code than I would care to write, which is grounds for closure as "Too Broad" (i.e. answers would require too much info to be considered a concise answer). I suppose there's no harm having this as an "answer", but it might get downvoted/flagged; hard to say. – Tim Lewis Nov 27 '19 at 20:00
  • 1
    You know what, I'll add an example in a bit ;) – PtrTon Nov 27 '19 at 20:01
  • what is this, this doesnt look like an answer – Shahid Karimi Oct 19 '20 at 19:26
  • I think this is the best answer. – NMO Feb 21 '22 at 11:56
  • This is a great solution but the command cant reference the seedclass as it is not available in the namespace. Does anybody have a solution to this? – nixn Sep 13 '22 at 12:30
12

you can ask for that limit before call any other seeders using

// DatabaseSeeder.php

$limit = $this->command->ask('Please enter the limit for creating something !!');

and then you can pass that limit to any additional seeders from 'DatabaseSeeder' like this

//DatabaseSeeder.php

$this->call(AnyAdditionalSeeder::class, false, compact('limit'));

then in 'AnyAdditionalSeeder' you can add parameter and name it $limit to the run() method like this

public function run($limit)
{
   // you can access limit variable here
}

then when you run the command php artisan db:seed it will ask you for the limit :)

Medo
  • 418
  • 7
  • 11
1

As of Laravel 8 you can use callWith to pass parameters to the run method of your seeders. Something like this:

class UsersTableSeeder extends Seeder
{    
    public function run($count = 1)
    {
        User::factory()->count($count)->create();
    }
}

And then your could use those seeders in other seeders like this:

class DatabaseSeeder extends Seeder
{
    public function run()
    {
        $this->callWith(UsersTableSeeder::class, ['count' => 10]);
    }
}

Note that the parameter array you give to callWith is associative, and its keys should match the run method's parameters, because the call will ordinarily be resolved through the Laravel's application container.

Tomas Buteler
  • 3,892
  • 4
  • 29
  • 42
0

my solution:

// MemberSeeder.php (example for Members Table)

namespace Database\Seeders;

use Illuminate\Database\Seeder;
use App\Models\Member as ModelsMember;

class MemberSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    static function run(int $nRec=1) {
        ModelsMember::factory()->times($nRec)->create();
    }
}

Call from a .php file

// Members.php
namespace App\Http\Livewire;

use Livewire\Component;
use App\Models\Member;
use Database\Seeders\MemberSeeder;

class Members extends Component
{
    public $members, $name, $email, $phone_number, $status, $member_id;
    public $bldModal = '';
    ...
    ...
    public function generaRecords() {
        MemberSeeder::run(2);
    }
}

Schema for to create table

        Schema::create('members', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('email')->unique();
            $table->string('phone_number');
            $table->char('status',1);
            $table->timestamps();
        });

Shortly: to change

public function run() {

To

static function run(int $nRec=1) {
0

you can pass a parameter as quantity to a seeder like this:

First, create a custom command

php artisan make:command generateFakeCompanyData

generateFakeCompanyData.php

<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Database\Seeders\CreateFakeCompanySeeder;

class generateFakeCompanyData extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'create:fake-comapnies {count}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Command description';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return int
     */
    public function handle(CreateFakeCompanySeeder $seeder)
    {
        $limit = $this->argument('count');
        $seeder->run($limit);
 
    }
}

create seeder file:

php artisan make:seeder CreateFakeCompanySeeder

CreateFakeCompanySeeder.php

<?php

namespace Database\Seeders;

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

class CreateFakeCompanySeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run(int $limit)
    {
        \App\Models\Company\Company::factory($limit)->create();
    }
}

create factory file

php artisan make:factory Company\CompanyFactory --model=Company

CompanyFactory.php

<?php

namespace Database\Factories\Company;

use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;
use App\Models\Blog;

/**
 * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Company\Company>
 */
class CompanyFactory extends Factory
{
    /**
     * Define the model's default state.
     *
     * @return array<string, mixed>
     */
    public function definition()
    {
        return [
            
            'name' => $this->faker->company,
            'email' => $this->faker->unique()->email,
            'logo' => $this->faker->imageUrl(640,480),
            'website' => Str::slug($this->faker->name).'.com',
            // 'website' => $this->faker->text(),
            
        ];
    }
}

in route: web.php

Route::controller(CompanyController::class)->group(function() {

    Route::prefix('company')->group(function () {
        Route::post('/store', 'companyInsert')->name('company.add'); 
    });

});

in controller: CompanyController.php

class CompanyController extends Controller{

    public function companyInsert(Request $request){

         $limit = $request->no_of_company;

         \Artisan::call('create:fake-comapnies '.$limit);

          return redirect()->back()->with('crudMsg','Total of '.$limit.' Company 
          Successfully Added');
    }
}
Mr. M
  • 7
  • 1
  • 3