Reputation: 2799
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
Reputation: 303
Additional you might forget about HasFactory trait
class Post extends Model
{
use HasFactory;
}
Upvotes: 0
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
Reputation: 154
Use this package if you are upgrading from laravel 7 to 8 composer require laravel/legacy-factories
Upvotes: 0
Reputation: 381
my problem was related with composer.lock file that was installing laravel v7, solved it with this command
composer update
Upvotes: 0
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
Reputation: 1936
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 !
Upvotes: 1
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
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
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
Reputation: 376
May be everything is perfect just run composer dump-autoload
. It happened to me.
Upvotes: 0
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:
Tests\TestCase
(instead of PHPUnit\Framework\TestCase
)setUp
function should be parent::setUp();
(I was missing this)Upvotes: 2
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
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
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
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