jcc5018's avatar

Laravel 8 factories, undefined methods

So, I decided to upgrade to laravel 8 from 7, and I've been running into a lot of issues. I think I solved most for now, but I'm currently having some difficulty with my factory calls in that i'm getting a call to undefined method errors. I'll write what i had to deal with below the current problem, in case im messing something up altogether, or to maybe help some others.

BUT, in my factories, i notice in the database testing 8.0 documentation the factory set up looks a bit different than what i have.

They have a simple:


    /**
     * Define the model's default state.
     *
     * @return array
     */
    public function definition()
    {
        return [
            'name' => $this->faker->name,
            'email' => $this->faker->unique()->safeEmail,
...

Whereas mine has this function call and such...

factory->define(User::class, function (Faker $faker) {
    $gender = $faker->randomElement($array = array ('male', 'female'));

    return [
        'first_name' => $faker->firstName($gender),
        'last_name' => $faker->lastName,


I'm not sure this is the cause of my problem, but a noticed difference. I probably need to review my OOD lessons to understand what's going on. But when updating i noticed composer said faker is no longer being used or something to that effect, yet, in the doc example they are still using it, though I'm not sure where its being called.

Anyway, I have my factory, and then i call it in my databaseSeeder file, along with the json files i have being seeded.

This used to work in laravel 7 but no longer does.

<?php
namespace Database\Seeders;
use App\Models\User;
use App\Models\Group;
use Illuminate\Database\Seeder;
use Database\Seeders\GroupTypes;
use Database\Seeders\TagsSeeder;
use Database\Seeders\UsersSeeder;
use Database\Seeders\StatesSeeder;
use Database\Seeders\HobbiesSeeder;
use Database\Seeders\RatingsSeeder;
use Database\Seeders\CurrencySeeder;
use Database\Seeders\TagablesSeeder;
use Database\Seeders\CountriesSeeder;
use Database\Seeders\Enum_typeSeeder;
use Illuminate\Support\Facades\Schema;
use Barryvdh\LaravelIdeHelper\Eloquent;
use Database\Seeders\BannerSizesSeeder;
use Database\Seeders\PersonalitySeeder;
use Illuminate\Database\Eloquent\Model;
use Database\Seeders\Enum_optionsSeeder;
use Database\Seeders\Connection_servicesSeeder;

class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application's database.
     *
     * @return void
     */
    public function run()
    {
        //Eloquent::unguard();
        Schema::disableForeignKeyConstraints();
     

        $this->call([
            TagsSeeder::class,
            HobbiesSeeder::class,
            Enum_optionsSeeder::class,
            Enum_typeSeeder::class,
            CurrencySeeder::class,
            TagablesSeeder::class,
            CountriesSeeder::class,
            StatesSeeder::class,
            languageSeeder::class,
            BannerSizesSeeder::class,
            UsersSeeder::class,
            RatingsSeeder::class,
            GroupTypes::class,
            PersonalitySeeder::class,
            Connection_servicesSeeder::class
        ]);

        $users= User::factory()->times(50)->create();
        $groups= Group::factory()->times(50)->create();
        
        $users->each(function (User $user) use ($groups)
        {$user->groups()->attach(
        $groups->random(rand(1,7))->pluck('id')->toArray(),
        [
        'status' => mt_rand(113,119),
        'role_id' =>1,
        'notification_freq' =>  mt_rand(110,112)
        ]
           );


});



        Schema::enableForeignKeyConstraints();
        Eloquent::reguard();
    }
}

First problem i ran into was it didnt recognize the Eloquent::unguard(); or reguard method.

Second, when calling the factories, I originally had it as:

   $users= factory(App\User::class, 50)->create();
        $groups= factory(App\Group::class, 50)->create();

but it didnt recognize the factory method, so i changed it to match the way the documents has it, but i get that undefined method error. I'm guessing i either have things set up wrong or im missing a USE ___

I probably got something else screwed up also, but that explains the current issue.

Now how i got there.

Updating composer was easy enough, but one of Laravel's changes was using the app/models directory, even though i know i could have kept them in APP, i have over 100 models so it did help to clean it up. Thought it'd be fairly easy, search and replace. But nope. i forgot there are also App/Consoles, App/Http, etc.

That was a pain getting everything squared away.

Then Laravel 7 model documents suggest using APP/modelName in its relationships, so that's how i had all 300+ relationships. Looking back, it may have still worked that way, but it didn't immediately work when testing so i checked the docs, and noticed it has Model::class for everything. (which is not in quotes, i learned) This wasn't so easy with find and replace, but after maybe an hour or so i now have all the relationships in the Laravel 8 format.

BUT my data wasn't being displayed properly. At least some of it. Some seemed to have no problem.

So i decided to rerun migrations which appeared to solve the problem for the seeder data that i was able to load, but that's where i ran into the factory issues.

on top of all that, I've got to figure out why my registration is not sending the data, or redirecting as i have set. But this broke before the upgrade so separate issue.

I wonder what else has been affected by me moving things to app/model folder?

0 likes
6 replies
jcc5018's avatar

well i tried that but it doesnt appear to address the undefined method issue. I have it formatted just like the 8.0 docs. but its not working.

to be clear, I'm talking about these 2 lines.

  $users= User::factory()->times(50)->create();
    $groups= Group::factory()->times(50)->create();

and the unguard/ reguard methods.

Here is the full error:


   BadMethodCallException 

  Call to undefined method App\Models\User::factory()

  at G:\xampp\htdocs\inah\vendor\laravel\framework\src\Illuminate\Support\Traits\ForwardsCalls.php:50
     46▕      * @throws \BadMethodCallException
     47▕      */
     48▕     protected static function throwBadMethodCallException($method)
     49▕     {
  ➜  50▕         throw new BadMethodCallException(sprintf(
     51▕             'Call to undefined method %s::%s()', static::class, $method
     52▕         ));
     53▕     }
     54▕ }

  • Bad Method Call: Did you mean App\Models\User::toArray() ?

  1   G:\xampp\htdocs\inah\vendor\laravel\framework\src\Illuminate\Support\Traits\ForwardsCalls.php:36
      Illuminate\Database\Eloquent\Model::throwBadMethodCallException("factory")

  2   G:\xampp\htdocs\inah\vendor\laravel\framework\src\Illuminate\Database\Eloquent\Model.php:1885
      Illuminate\Database\Eloquent\Model::forwardCallTo(Object(Illuminate\Database\Eloquent\Builder), "factory", [])


fkhan's avatar

Hello @jcc5018 I am facing the very same issue and can't really find anything out there. Did you find the solution to this issue ?

jcc5018's avatar

I think I did, but that was 5 months ago so I really can't remember what I did.

I may have just redid factories and such completely with the laravel 8 way, instead of trying to convert.

But I really don't remember, sorry.

hassam's avatar

@jcc5018 you forgot to add HasFactory trait in Models;

 <?php

namespace App\Models;

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

class Category extends Model
{
    use HasFactory;
}

2 likes
tcharlezin's avatar

If someone is coming to check how to resolve. Following the documentation of Laravel, it mention for you to install the laravel/legacy-factories

When you do, if you extend your new class UserFactory from Illuminate\Database\Eloquent\Factory it will say that some methods don't exists. And in fact, don't exists.

You need to extend Illuminate\Database\Eloquent\Factories\Factory instead of Illuminate\Database\Eloquent\Factory, this was the mistake.

Please or to participate in this conversation.