Peter Amo
Peter Amo

Reputation: 201

How to send a value as parameter to the Factory Class

I need to run a Factory 50 times, so inside the DatabseSeeder:

public function run()
{
    for($i=1;$i<=50;$i++){
       (new CategoryQuestionFactory($i))->create();
    }
}

So as you can see, I tried passing a variable called $i as parameter to CategoryQuestionFactory class.

Then at this Factory, I tried this:

class CategoryQuestionFactory extends Factory
{
    protected $counter;

    public function __construct($c)
    {
        $this->counter = $c;
    }
    /**
     * Define the model's default state.
     *
     * @return array<string, mixed>
     */
    public function definition()
    {
        $question = Question::find($this->counter);

        return [
            'category_id' => $this->faker->numberBetween(1,22),
            'question_id' => $question->id
        ];
    }
}

But when I run php artisan db:seed at Terminal, I get this error:

Call to a member function pipe() on null

at C:\xampp\htdocs\forum\root\vendor\laravel\framework\src\Illuminate\Database\Eloquent\Factories\Factory.php:429

So what's going wrong here? How can I properly send a value as a parameter to the Factory Class?

Also, at the IDE for the __construct method of this Factory, I get this message:

enter image description here


UPDATE #1:

Here is the capture of error at IDE:

enter image description here

Upvotes: 2

Views: 1160

Answers (4)

Dmitry Leiko
Dmitry Leiko

Reputation: 4372

I've generated the model via PhpStrom:

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Collection;

class CategoryQuestionFactory extends Factory
{
    public function __construct($count = null, ?Collection $states = null, ?Collection $has = null, ?Collection $for = null, ?Collection $afterMaking = null, ?Collection $afterCreating = null, $connection = null, ?Collection $recycle = null)
    {
        parent::__construct($count, $states, $has, $for, $afterMaking, $afterCreating, $connection, $recycle);
    }

    public function definition()
    {
        $question = Question::find($this->counter);

        return [
            'category_id' => $this->faker->numberBetween(1,22),
            'question_id' => $question->id
        ];
    }
}

It's should work fine. I checked. You should call parent::__construct.

Like constructors, parent destructors will not be called implicitly by the engine. In order to run a parent destructor, one would have to explicitly call parent::__destruct() in the destructor body. Also like constructors, a child class may inherit the parent's destructor if it does not implement one itself.

Upvotes: 1

gaetan-hexadog
gaetan-hexadog

Reputation: 67

Don't forget to call parent::__construct() in the constructor of your CategoryQuestionFactory factory. Your CategoryQuestionFactory is supposed to extends Laravel standard Factory. Missing to call the parent constructor on a child class breaks the code.

Upvotes: 1

HashtagForgotName
HashtagForgotName

Reputation: 671

In laravel its better to associate with the model, So instead of doing this

$question = Question::find($this->counter);

return [
     'category_id' => $this->faker->numberBetween(1,22),
     'question_id' => $question->id
];

you can do this (then you dont have to passs the $i)

return [
     'category_id' => $this->faker->numberBetween(1,22),
     'question_id' => Question::factory(),
];

Upvotes: 0

xenooooo
xenooooo

Reputation: 1216

It seems to me that you want to seed the intermediate table. There are methods that can be use when seeding them one of them is has() which is the one i always use.

/**
* will create a one question and 3 category then create a data in the intermediate table. 
* expected data : 
* question_id | category_id
*     1            1
*     1            2
*     1            3
*/
Question::factory()->has(
    Category::factory()->count(3)
)->create();

So let's say you want to create a 100 question and 5 categories

/**
* will create a 100 question and 5 category then create a data in the intermediate table. 
* expected data : 
* question_id | category_id
*     1            1
*     1            2
*     1            3
*     1            4
*     1            5
*     2            1
*     2            2
*     2            3
*     2            4
*     2            5
* until the 100th question will have a 5 categories
*/
Question::factory(100)->has(
    Category::factory()->count(5)
)->create();

Upvotes: 2

Related Questions