Reputation: 673
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
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