简体   繁体   中英

Custom Factory class not found on my Laravel package

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?

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM