Search code examples
phplaravelweblaravel-8laravel-artisan

Why is php artisan make:factory not Generating with a Model


So long story short, I have a model in my Larvel 8 (Jetstream) application called Board. I am trying to generate a factory for this Board model.

When I use either of the commands below:

php artisan make:factory BoardFactory

or

php artisan make:factory BoardFactory --model=Board

I get a factory class generated with seemingly no errors or issues. However, when I open the class it contains nothing to do with the model.

<?php

namespace Database\Factories;

use Illuminate\Database\Eloquent\Factories\Factory;

class BoardFactory extends Factory{
    /**
     * Define the model's default state. 
     *
     * @return array
     */
    public function definition()
    {
        return [
            //
        ];
    }
}

I have tried this with all the Model's within my application and this persists. Once again no error to say the model is not found. The command seemingly runs successfully but obviously hasn't generated the factory for the Model.

I know I can easily write this manually if needs be, but I would like to understand why this isn't working and how I can fix it. The faster I can get through my testing... the better :)

Thanks in advance for any help.


Solution

  • Try publishing your laravel stubs and confirm that the stub file contents are defined as expected.

    1. Publish the stubs.

    php artisan stub:publish

    • This should create a /stubs folder in the root project directory.
    • Inside that folder, you will see all stubs.
    1. Most specifically, open the stub file called factory.stub
    • It's file contents should look something similar to this:
    <?php
    
    namespace {{ factoryNamespace }};
    
    use Illuminate\Database\Eloquent\Factories\Factory;
    use {{ namespacedModel }};
    
    class {{ factory }}Factory 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 [
                //
            ];
        }
    }
    
    

    Notes:

    From the looks of it, it appears as if your current factory stub is missing the section(s) below:

    // ...
    use {{ namespacedModel }};
    // ...
    
        /**
         * The name of the factory's corresponding model.
         *
         * @var string
         */
        protected $model = {{ model }}::class;
    
    // ...
    

    Ideally speaking, in normal (default) cases, running a command that generates a factory with a linked model should look like this:

    Command:

    php artisan make:factory BoardFactory --model=Board

    Expected Output File (database/factories/BoardFactory.php):

    <?php
    
    namespace Database\Factories;
    
    use App\Models\Board;
    use Illuminate\Database\Eloquent\Factories\Factory;
    
    class BoardFactory extends Factory
    {
        /**
         * The name of the factory's corresponding model.
         *
         * @var string
         */
        protected $model = Board::class;
    
        /**
         * Define the model's default state.
         *
         * @return array
         */
        public function definition()
        {
            return [
                //
            ];
        }
    }
    
    

    Addendum:

    As pointed out in a comment by @miken32, in Laravel versions published later than Oct 22, 2021, declaring a model attribute in your Factory class will no longer be necessary:

    Laravel Pull Request

    At this time, database factories have this hidden feature where database models can be "guessed".

    So, this pull request proposes that remove protected $model from the Factory stub, as probably the current "guess" logic works for 99.99% of the people. In addition, I've also pull requested to the skeleton that we remove protected $model = User::class from the UserFactory.php: laravel/laravel#5713.