Welcome to the Treehouse Community

The Treehouse Community is a meeting place for developers, designers, and programmers of all backgrounds and skill levels to get support. Collaborate here on code errors or bugs that you need feedback on, or asking for an extra set of eyes on your latest project. Join thousands of Treehouse students and alumni in the community today. (Note: Only Treehouse students can comment or ask questions, but non-students are welcome to browse our conversations.)

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and a supportive community. Start your free trial today.

PHP Build a REST API with Laravel Seeding the Database Factories and Seeders

Jonathan Grieve
MOD
Jonathan Grieve
Treehouse Moderator 90,704 Points

Changes for Laravel v8: Factories, Seeders and Models

Hi Students!

Since the course has been released I've been going through the course for a third time and I'm now working through the course in Laravel version 8. So some of the code in the videos is sadly now out of date.

Here are some of the changes I've seen so far as to what the differences are. The artisan commands used remain the same.

Creating Models

  • In a change to v8 of Laravel, Models now include use of hasFactory. Keep this change.
<?php

namespace App\Models;

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

class Owner extends Model
{
    use HasFactory;
}

Database Seeders

  • In Laravel 8: DatabaseSeeder.php now contains a call to generate 10 records - uncommented by default. You should call the Database Seeder files in the same way as demonstrated.
DatabaseSeeder.php
<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application's database.
     *
     * @return void
     */
    public function run()
    {
        // User::factory(10)->create();
        $this->call( NamedTableSeeder::class );. 
        $this->call( NamedTableSeeder::class );
    }
}

Factories in Laravel 8

  • Factories have undergone a big change in Laravel 8. This is what you get when you now create Factories in Artisan
<?php

namespace Database\Factories;

use App\Models\Model;
use Faker\Generator\ as Faker;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;

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

    /**
     * Define the model's default state.
     *
     * @return array
     */
    public function definition()
    {
        return [
            //
        ];
    }
}
  • The generated template files for Factories now define Factories in a different public method.

  • Change any reference to Model to the name of the Model in your Factory files.

  • Import the Faker Library as demonstrated.

  • In your function definition use the $this variable rather than $faker as a variable to use the Faker Library

<?php 
public function definition()
    {
        return [
            //
            "url" => $this->faker->name,
            "caption" => $this->faker->text,
            "owner_id" => rand(1, \App\Models\Owner::count())
        ];
    }
}
?>
  • NamedTableSeeder.php -

Model Seeder Files

NamedSeederFile.php
<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;

class NamedTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        //connect factory to seeder
        //factory( \App\Models\Model::class, 10)->create();
        \App\Models\Models::factory()->count(10)->create(); 

    }
}
  • Change the call to the Models that connect your Factory Files to your Seeder files. so it is an imported call rather than a method call.

I hope this post helps users struggling with the changes to Laravel in following this course!

1 Answer

On AuthorsTableSeeder.php file, I've edited my run method like this:

public function run() { \App\Models\Author::factory()->count(10)->create(); }

When I run "php artisan db:seed", I'm getting this error:

Seeding: Database\Seeders\AuthorsTableSeeder

   BadMethodCallException 

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

  at 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\Author::toArray() ? 

      +3 vendor frames 
  4   database/seeders/AuthorsTableSeeder.php:16
      Illuminate\Database\Eloquent\Model::__callStatic("factory", [])

      +7 vendor frames 
  12  database/seeders/DatabaseSeeder.php:16
      Illuminate\Database\Seeder::call("Database\Seeders\AuthorsTableSeeder")

Any idea what could be wrong?