Ahmed Khattab
Ahmed Khattab

Reputation: 2799

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.

Upvotes: 49

Views: 71567

Answers (15)

Adrug
Adrug

Reputation: 303

Additional you might forget about HasFactory trait

class Post extends Model
{
   use HasFactory;
}

Off doc

Upvotes: 0

chieeu.73
chieeu.73

Reputation: 21

I'm getting the same problem ! Just add this to your Model. It worked for me !

protected static function newFactory()
{
    return new ourFactory();
} 

Upvotes: 1

Ashutosh Jha
Ashutosh Jha

Reputation: 154

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

Upvotes: 0

Guillermo Silva
Guillermo Silva

Reputation: 381

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

composer update

Upvotes: 0

Zilbert97
Zilbert97

Reputation: 560

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

Upvotes: 5

lotfio
lotfio

Reputation: 1936

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

enter image description here

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 !

Upvotes: 1

Nerjuz
Nerjuz

Reputation: 1061

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

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

Upvotes: 2

aphoe
aphoe

Reputation: 2716

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

Upvotes: 4

Amit Gupta
Amit Gupta

Reputation: 2806

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.

Upvotes: -2

softech
softech

Reputation: 376

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

Upvotes: 0

Entity
Entity

Reputation: 8202

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)

Upvotes: 2

Johhn
Johhn

Reputation: 1039

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

e.g. app\models\User- will match to database/factories/UserFactory

finally ensure you run: composer dumpautoload

Upvotes: 7

philthathril
philthathril

Reputation: 506

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.

Upvotes: 10

Abouhassane Abdelhamid
Abouhassane Abdelhamid

Reputation: 453

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.

Upvotes: 24

lagbox
lagbox

Reputation: 50491

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

Upvotes: 71

Related Questions