简体   繁体   中英

Laravel 8, Model factory class not found

so when using the new model factories class introduced in laravel 8.x, ive this weird issue saying that laravel cannot find the factory that corresponds to the model. i get this error

PHP Error:  Class 'Database/Factories/BusinessUserFactory' not found in .....

tho ive followed the laravel docs, ive no idea whats going on

Here is the BusinessUser class

<?php

namespace App;

use Database\Factories\BusinessUserFactory;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class BusinessUser extends Model
{
    use HasFactory;
}

and the factory

<?php

namespace Database\Factories;

use App\BusinessUser;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;

class BusinessUserFactory extends Factory
{
    /**
     * The name of the factory's corresponding model.
     *
     * @var string
     */
    protected $model = BusinessUser::class;

    /**
     * Define the model's default state.
     *
     * @return array
     */
    public function definition()
    {
        return [
            'name' => "dsfsf"
        ];
    }
}


any ideas or leads is greatly appreciated.

If you upgraded to 8 from a previous version you are probably missing the autoload directive for the Database\\Factories namespace in composer.json :

"autoload": {
    "psr-4": {
        "App\\": "app/",
        "Database\\Factories\\": "database/factories/",
        "Database\\Seeders\\": "database/seeders/"
    }
},

You can also remove the classmap part, since it is no longer needed.

Run composer dump after making these changes.

Laravel 8.x Docs - Upgrade Guide - Database - Seeder and Factory Namespace

Apparently you have to respect the folder structure as well. For example, if you have the User Model in the following path: app\\Models\\Users\\User , then the respective factory should be located in database\\factories\\Users\\UserFactory .

I'm in the process of migrating from laravel 7 to 8.

After banging my head against the wall for a while and looking at the source code, I saw that you can optionally override what factory class gets called for a model using the newFactory method on the model.

I also then noticed that it IS in the documentation ( https://laravel.com/docs/8.x/database-testing#creating-models ) - I just didn't understand what it meant the first time I read it. Now I do.

I solved this by the following:

<?php

namespace My\Fancy\Models;

use Database\Factories\SomeFancyFactory;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class SomeClass extends Model
{
    use HasFactory;

    /** @return SomeFancyFactory */
    protected static function newFactory()
    {
        return SomeFancyFactory::new();
    }
}

After this change, my tests passed as expected.

You need to ensure that the namespace is the same: as shown below: otherwise this will screw you up big time. The name of the factory is the name of the model + Factory

eg app\\models\\User - will match to database/factories/UserFactory

finally ensure you run: composer dumpautoload

In my own case, it happened in a Laravel 8 project ie it wasn't a project I upgraded from Laravel 7. And I noticed this after doing composer update recently.

1: When creating the model, create the factory alongside

php artisan make:model BusinessUser -f // -f creates the factory

2: For your older models comment out use HasFactory; or just create the factory

php artisan make:factory BusinessUserFactory -m

Let's say your model Example is under the App\Example\Models namespace. If you want ALL of your factories under database\factories , then you could define the namespace for your all of factories in your AppServiceProvider :

// ...

use Illuminate\Database\Eloquent\Factories\Factory;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        Factory::guessFactoryNamesUsing(function (string $modelName) {
            return 'Database\\Factories\\'.class_basename($modelName).'Factory';
        });
    }
}

And then in your factory, located in database/factories/ExampleFactory.php :

namespace Database\Factories;

use Illuminate\Database\Eloquent\Factories\Factory;

class ExampleFactory extends Factory
{
    // ...
}

...as per this twitter comment (I can't take credit for this solution but sharing the fix:): https://twitter.com/ejunker/status/1306007589940068352/photo/1

I was having this same issue, but for a different reason. If you're using factories in the setUp function of a test, make sure:

  1. You're extending Tests\\TestCase (instead of PHPUnit\\Framework\\TestCase )
  2. The first line of your setUp function should be parent::setUp(); (I was missing this)

May be everything is perfect just run composer dump-autoload . It happened to me.

Add this to AppServiceProvider::boot() to prevent namespace of model guessing.

Factory::guessFactoryNamesUsing(function (string $modelName) {
        return 'Database\\Factories\\' . Arr::last(explode('\\', $modelName)) . 'Factory';
    });

It seems like a laravel core issue ! it was caused by the modelName() method located in Illuminate\Database\Eloquent\Factories\Factory.php

在此处输入图像描述

Issue was fixed 10 days ago by laravel maintainers in this commit Fix commit and this release 8.82.0

You can fix the issue by upgrading your laravel version to 8.82.0

Hope this saves you some time. cheers !

my problem was related with composer.lock file that was installing laravel v7, solved it with this command

composer update

Use this package if you are upgrading from laravel 7 to 8 composer require laravel/legacy-factories

Today I have got below issue after upgrading my project from Laravel 7 to Laravel 8 and updating it online on server.

Trait 'Illuminate\Database\Eloquent\Factories\HasFactory' not found

Even I have updated composer.json with autoload directive given in answer by @lagbox but it did not resolved the issue for me.

Finally I have updated complete vendors folder online that have resolved my issue.

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