Danaq
Danaq

Reputation: 673

Laravel calling seeder in subdirectory - Class not found

Laravel (currently 8.12 | php 7.4.14) started throwing errors a few days ago when I try to execute a seeder in a subdirectory via Artisan::call.

On bash this command works fine:

php artisan db:seed --class=Database\\Seeders\\Testing\\StagingTestDataSeeder

But I want to execute it as:

Artisan::call("db:seed --class=Database\\Seeders\\Testing\\StagingTestDataSeeder");

The result is: Target class [Database\\Seeders\\DatabaseSeedersTestingStagingTestDataSeeder] does not exist. Which is absolutely correct as there are no namespace delimiters in the argument. Beacuse there are no delimiters in the argument, the getSeeder-method just concats the argument to the base namespace of database seeders
(see below if (strpos($class, '\\') === false) {).

Because it works on bash I don't thinkt that there are any mistakes with namespace or file location.
I dumped some data in the Illuminate\Database\Console\Seeds\SeedCommand.php::66

/**
     * Get a seeder instance from the container.
     *
     * @return \Illuminate\Database\Seeder
     */
    protected function getSeeder()
    {
        $class = $this->input->getArgument('class') ?? $this->input->getOption('class');
        dump($this->options());
        dump($this->arguments());
        dump($class);
        if (strpos($class, '\\') === false) {
            $class = 'Database\\Seeders\\' . $class;
        }

        if (
            $class === 'Database\\Seeders\\DatabaseSeeder' &&
            !class_exists($class)
        ) {
            $class = 'DatabaseSeeder';
        }

        return $this->laravel->make($class)
            ->setContainer($this->laravel)
            ->setCommand($this);
    }

which prints this:

array:10 [▼
  "class" => "DatabaseSeedersTestingStagingTestDataSeeder"
  "database" => null
  "force" => false
  "help" => false
  "quiet" => false
  "verbose" => false
  "version" => false
  "ansi" => null
  "no-interaction" => false
  "env" => null
]
array:2 [▼
  "command" => "db:seed"
  "class" => null
]
"DatabaseSeedersTestingStagingTestDataSeeder"

Somehow the escaped backslash does not reach the getSeeder-method of the SeedCommand-class.
I know that I could load the class with pure PHP via require or add the deep namespace to the composer.json. But as this is not the intended use by laravel I want to figure out how to do it with onboard functionality.

---- a few tests later ----

I figured out that I can pass the class/ namespace value as option (with --class=) as well as argument (just the namespace) to the SeedCommand.php. So Artisan::call("db:seed Database\\\\Seeders\\\\Testing\\\\StagingTestDataSeeder"); works now.

Can someone explain what happens there? I'm totally confused why I need to pass the double amount of backslashes. It seems that the argument is interpreted twice or something.
Was the SeedCommand recently updated?

Upvotes: 1

Views: 1775

Answers (1)

Davit Zeynalyan
Davit Zeynalyan

Reputation: 8618

Use

Artisan::call('db:seed', ['--class' => Database\Seeders\Testing\StagingTestDataSeeder]);

look more details https://laravel.com/docs/8.x/artisan#programmatically-executing-commands

Upvotes: 4

Related Questions