Laravel 8, Model factory class not found - php

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
e.g. 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:
You're extending Tests\TestCase (instead of PHPUnit\Framework\TestCase)
The first line of your setUp function should be parent::setUp(); (I was missing this)

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 !

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

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.

Related

Laravel Sanctum default model customization

I use in my Laravel application `MongoDB as a database driver using composer package:
https://github.com/jenssegers/laravel-mongodb
By default, Laravel models extend Illuminate\Database\Eloquent\Model class.
But when I use MongoDB then my models must extend the Jenssegers\Mongodb\Eloquent\Model` class instead of default Laravel class.
How I can now replace Laravel Sanctum default extending model class Laravel\Sanctum\PersonalAccessToken to Jenssegers\Mongodb\Eloquent\Model.
Example
<?php
namespace Laravel\Sanctum;
// use Illuminate\Database\Eloquent\Model; // Replace this class
use Jenssegers\Mongodb\Eloquent\Model; // To this class
use Laravel\Sanctum\Contracts\HasAbilities;
class PersonalAccessToken extends Model implements HasAbilities
{
// sanctum model
}
Now I can do this inside the vendor folder but I think it's the incorrect way. How to solve this problem correctly?
What you need to do is create a custom PersonalAccessToken (you can just copy the original one "Laravel\Sanctum\PersonalAccessToken.php")
then just change
use Illuminate\Database\Eloquent\Model
for
use Jenssegers\Mongodb\Eloquent\Model
and finally in \Providers\AuthServiceProvider
you must add in the boot function
public function boot()
{
$this->registerPolicies();
Sanctum::usePersonalAccessTokenModel(PersonalAccessToken::class);
}
in my search I found this package:
Laravel-Sanctum-Mongo
It can serve you, basically it is just installing
Or
Step 1:
Copy this Model \Laravel\Sanctum\PersonalAccessToken and paste in your custom model \App\Models\Sanctum\PersonalAccessToken
Step 2:
Find the use Illuminate\Database\Eloquent\Model; and replace with use Jenssegers\Mongodb\Eloquent\Model;
Step 3:
In the App\Providers\AppServiceProvider add this:
// Loader Alias
$loader = AliasLoader::getInstance();
// SANCTUM CUSTOM PERSONAL-ACCESS-TOKEN
$loader->alias(\Laravel\Sanctum\PersonalAccessToken::class, \App\Models\Sanctum\PersonalAccessToken::class);
and Ready, work for me
I had also to add in the vendor folder NewAccessToken file this:
use App\Models\Sanctum\PersonalAccessToken;
As per this issue sanctum only support extending the default model and are probably not going to consider adding an interface.
But we can trick autoloader into loading our class instead of the default one.
Here is how to do it:
Step 1: Copy the /vendor/laravel/sanctum/src/PersonalAccessToken.php file to /app/overrides/PersonalAccessToken.php
Step 2: Edit the /app/overrides/PersonalAccessToken.php and replace use Illuminate\Database\Eloquent\Model; with use Jenssegers\Mongodb\Eloquent\Model;
Step 3: Edit your composer.json file and edit the autoload section to look like the following:
"autoload": {
"exclude-from-classmap": ["vendor\\laravel\\sanctum\\src\\PersonalAccessToken.php"],
"psr-4": {
"App\\": "app/",
"Database\\Factories\\": "database/factories/",
"Database\\Seeders\\": "database/seeders/",
"Laravel\\Sanctum\\": "app/overrides/"
}
},
Step 4: run composer dump-autoload
This fixed my issue in the windows machine but the solution might not work for different OS because I've not tried them all. (Please comment your os name if this worked in your os)
Credits to https://github.com/laravel/sanctum/issues/263

Laravel webwizo shortcodes package Shortcodes class not found

I recently started using laravel so i'm a beginner, and right now i'm working on a small project which requires me use shortcodes(like the ones in wordpress).
So i searched for a little bit and found this package:
https://packagist.org/packages/webwizo/laravel-shortcodes
I ran the installation and usage the way it's written but i get the error : Class 'App\Providers\Shortcode' not found in the provider I have to make using the laravel make:provider command as specified in the package instructions, below is my exact usage and install code.
added this to the providers array :
/*
* shortcodes providers
*/
Webwizo\Shortcodes\ShortcodesServiceProvider::class,
App\Providers\ShortcodesServiceProvider::class,
Added this to aliases:
'Shortcode' => Webwizo\Shortcodes\Facades\Shortcode::class,
this is the content of my ShortcodesServiceProvider in app/providers:
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use App\Shortcodes\JobsForm;
class ShortcodesServiceProvider extends ServiceProvider
{
/**
Bootstrap the application services.
*
#return void
*/
public function boot()
{
//
}
/**
Register the application services.
*
#return void
*/
public function register()
{
Shortcode::register('jobs', JobsForm::class);
}
}
I use laravel 5.4 so that might be an issue.
The thing is the class obviously exists, it gives the Shortcodes class not found error because I think it searches for it in the app/providers/ShortcodesServiceProvider file, and obviously it's not there it's in the vendor file.
Is there something I'm missing i've checked and double checked, I can't seem to get this thing to work.
It shoould work considering it has an alias defined right ?
I used it in the view like this:
return view('quarx-frontend::pages.' . $page->template)->with('page', $page)->withShortcodes();
Thanks for taking the time to read this any help would be much appreciated.
If you need any more info I'll be glad to supply it.
p.s. sorry for bad english ,not a native speaker :P
It searches for Shortcode in the App\Providers; namespace and not in the root namespace where the Facade is defined.
You can fix this in App\Providers\ShortcodesServiceProvider.php by either doing:
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use App\Shortcodes\JobsForm;
use Shortcode;
class ShortcodesServiceProvider extends ServiceProvider
{
Or use \Shortcode
/**
* Register the application services.
*
* #return void
*/
public function register()
{
\Shortcode::register('jobs', JobsForm::class);
}
I would recommend the first option.

Laravel 5.3, Eloqent models and Namespace Issues

I am confused. I am following the laravel document to the T and something isn't being configured properly maybe?
The Short: I can't use my Eloquent models like the documentation shows.
The Long:
I followed these steps from the Laravel docs.
laravel new blog
added database details to .env
created a model: php artisan make:model SavedService
namespace App;
use Illuminate\Database\Eloquent\Model;
/**
* #property integer $service_id
* #property string $title
* #property string $price
* #property string $short_description
* #property string $long_description
* #property integer $display
*/
class SavedService extends Model
{
protected $table = 'saved_services';
public $timestamps = false;
/**
* #var array
*/
protected $fillable = ['title', 'price', 'short_description', 'long_description', 'display'];
}
created a controller: php artisan make:controller datatest
added index method to controller:
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\SavedService;
class datatest extends Controller
{
public function index() {
$flights = App\SavedService::all();
foreach ($flights as $flight) {
echo $flight->name;
}
}
}
Now, use App\SavedService; is highlighted in PHPStorm: "SavedServices is never used."
Also, for $flights = App\SavedService::all();, App is highlighted in red: "Undefined namespace App." SavedService is highlighted and PHPStorm tells me "Undefined class SavedService."
If I let PHPStorm create the SavedService class, its namespace is App/Http/Controllers/App
??
Project structure is
app
-composer.json
-Http\
-SavedService.php
--Controllers\
---dataTest.php
My composer.json autoload:
"autoload": {
"classmap": [
"database"
],
"psr-4": {
"App\\": "app/"
}
},
EDIT:
Sorry, had to rush, train got into the station! I wanted to add to this a few things. First, I am using a vagrant machine to host the projects, not sure if that is important to know? Second, I wanted to use Propel-orm. I find eloquent not very eloquent at all. I couldn't get propel to work, something to do with namespaces. The propel generated models would be in app/Http/Models/Http/Models/ModelName. I am beginning to think this is all one problem.
I am not doing anything extra ordinary to the process. Just following the steps in the documentation.
Additionally, Eloquent doesn't seem to work the way the eloquent documentation hosted on the Laravel docs page. For example "get()" eloquentModel::get(). The laravel docs shows it as that, get(), and phpstorm throws a fit saying $key is expected. The eloquent documentation confirms, get($key). What am I missing there? Why the difference, and why isn't it mentioned in the documentation. Maybe this has something to do with my current issue? Maybe the answer the this will solve why I can't use propel?
END EDIT.
What am I missing? I'm so confused, why isn't this just working? Help please!!! Thanks
change
$flights = App\SavedService::all();
to
$flights = SavedService::all();

Troubleshooting referencing a model in a laravel controller

I've been trying unsuccessfully to resolve an error in a laravel 5.2 app (carfreak).
FatalErrorException in PropertyController.php line 85:
Class 'App\Models\CarModel' not found
I have moved the default user model to a folder app/models and made the necessary changes so that it's all working fine.
Now I have a new controller CarController, and a new model, CarModel that are just not working. It seems to be such a simple problem with namespaces, but I am unable to resolve it.
is the model in the models folder? Yes. carfreak\app\Models\CarModel.php
is the controller namespace correct? Yes... namespace carfreak\Http\Controllers;
does the controller reference the model? Yes...use App\Models\CarModel;
is the model namespace correct? Yes... namespace carfreak\Models;
I am able to create different versions of the error by playing with the CarController but no permutation I can think of has worked.
EDIT: Controller and Model added...
EDIT: More details added:
The irony of this is that I can php artisan make:model sanityCheck and it will create a model in the \app root (i.e. not in app\models)... and that model can be called just fine. If I put my CarController back in the root, and change it's namespace appropriately, it still doesn't work. It's almost like I have some stupid spelling error in the class name or something, but I've copied and pasted class names into my filename, class declaration, "use" declarations, etc. and it. still. doesnt. work. Aargh!
//this is carModel
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class CarModel extends Model
{
//
/**
* The attributes that are mass assignable.
* #var array
*/
protected $fillable = [
'colourOfCar',
];
}
//this is carController
<?php
namespace carfreak\Http\Controllers;
use Illuminate\Http\Request;
//use \carfreak\app\Models\CarModel;
use App\Models\CarModel;
class CarController extends Controller
{
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function __construct()
{
$this->middleware('auth');
}
public function store(Request $request)
{
// validate the data
$this->validate($request, array(
'CarColour' => 'required|max:50'
));
// store in the database
$newCar = new CarModel;
dd($request);
}
}
This looks wrong use \carfreak\app\Models\CarModel; should be use App\Models\CarModel in this is carController
Casing is important on linux. The namespace generally is used in a PSR Aloader to find the file. And Linux filesystem is case sensitive. So the CareModel.php file should be located in App/Models/CarModel.php
But I never used Laravel...
Well, here it is. I solved it by asking myself this question: If I'm having so much trouble namespacing, referencing and organising my models, then maybe I can get artisan to do it for me.
The post that got me thinking differently was Mansoor Akhtar's advice here: How do I instruct artisan to save model to specific directory?
Get artisan to make the model in the right place first time.
php artisan make:model Models/CarModel
In the Controller, reference the model correctly
use name-of-app\Models\CarModel;
There may or may not be cache flushing involved in my problem. I was eventially restarting my XAMPP after every change to ensure no caching was involved. I also tried
php artisan cache:clear

Method ::find not found in Laravel 5.2 / Eloquent

In Laravel 5.2 I made a folder app/Models.
This is one of my models: app/Models/Pin.php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Pin extends Model {
protected $table = 'pins';
}
In my composer.json I added to "classmap": app/Models.
Then I runned composer dump-autoload
In my PinController, I have:
use App\Models\Pin as Pin;
When I do: Pin::all(); it returns a collection.
But when I try: Pin::find(1); I get:
Method find not found in class \App\Models\Pin
Is their a way I can get all methods from Eloquent?
I see nothing wrong with your approach. It should be working, and it works if I try it on a clean Laravel 5.2.5 install. Maybe some other dependencies are causing side effects for you. Have you tried to isolate the problem on a clean install?
You can find all Eloquent methods in the API docs, but keep in mind the Model class has a magic __call() method. This is why you won't see a find() method directly in the Model class; instead calls to Model::find() will be passed to the Builder::find()method.

Categories