Reputation: 1221
I'm creating a package that will serve as a base for projects, and I'm stuck on the creation of factories. For the package, I use the namespace Gad\Base
.
I created a model MyModel
in src/
:
namespace Gad\Base;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class MyModel extends Model
{
use HasFactory;
protected $guarded = [];
}
and the corresponding factory MyModelFactory
in database/factories/
:
namespace Database\Factories;
use Gad\Base\MyModel;
use Illuminate\Database\Eloquent\Factories\Factory;
class MyModelFactory extends Factory
{
protected $model = MyModel::class;
public function definition()
{
return [
'something' => $this->faker->text(100),
];
}
}
But when I try to use the factory (in a test, for example)
MyModel::factory()->create()
I get the following error:
Error: Class "Database\Factories\Gad\Base\MyModelFactory" not found
I am not sure why looks for Database\Factories\Gad\Base\MyModelFactory
and not for Database\Factories\MyModelFactory
.
This is how I defined my autoload in composer.json
:
"autoload": {
"psr-4": {
"Gad\\Base\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Gad\\Base\\Tests\\": "tests/",
"Database\\Factories\\": "database/factories/"
}
}
If in MyModel
I override the static function newFactory()
like this:
protected static function newFactory()
{
return new MyModelFactory();
}
Everything works fine. Anyone knows what I did wrong?
Upvotes: 0
Views: 1030
Reputation: 17216
The answer is in the resolver for factory name Illuminate/Database/Eloquent/Factories/Factory.php@798
/**
* Get the factory name for the given model name.
*
* @param class-string<\Illuminate\Database\Eloquent\Model> $modelName
* @return class-string<\Illuminate\Database\Eloquent\Factories\Factory>
*/
public static function resolveFactoryName(string $modelName)
{
$resolver = static::$factoryNameResolver ?? function (string $modelName) {
$appNamespace = static::appNamespace();
$modelName = Str::startsWith($modelName, $appNamespace.'Models\\')
? Str::after($modelName, $appNamespace.'Models\\')
: Str::after($modelName, $appNamespace);
return static::$namespace.$modelName.'Factory';
};
return $resolver($modelName);
}
It checks if the model is in the namespace \App\Models\
(or more precisely \$appNamespace\Models\
) like standard models of the app, if not it apprends the namespace of the model and add the suffix Factory
to it.
Upvotes: 0