2

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

Pouya
  • 114
  • 1
  • 8
  • 36
  • Can you add the full stack-trace to your question? – Lajos Arpad Nov 28 '22 at 07:41
  • @LajosArpad Please see **UPDATE #1**, this error occurs at the Terminal – Pouya Nov 28 '22 at 07:50
  • 1
    Can you explain what are you trying to achieve ? – xenooooo Nov 28 '22 at 09:38
  • @xenooooo I have updated my question, please see it once more – Pouya Nov 28 '22 at 09:39
  • I don't understand your question ? Sorry. Do you want to seed ? the Intermediate Table of the `many to many` relationship ? – xenooooo Nov 28 '22 at 09:42
  • @xenooooo Look, I have 50 questions exist at the `questions` table. There is a Many-To-Many relationship between Question model & Category model. And for the pivot table which is `category_question`, I have created a single model named `CategoryQuestion`. Now I need to run a Factory for creating some dummy data inside this pivot table, fifty times (for each question). Therefore I need to pass a parameter to the Factory class which shows the counter of question ids. – Pouya Nov 28 '22 at 09:55
  • Does the question also a dummy data ? – xenooooo Nov 28 '22 at 09:55
  • [Better way of Seeding a Pivot Table](https://stackoverflow.com/questions/23433209/better-way-of-seeding-a-pivot-table) – steven7mwesigwa Dec 03 '22 at 06:11
  • [Laravel 8: How to seed a pivot table in many to many relationship](https://stackoverflow.com/questions/66044468/laravel-8-how-to-seed-a-pivot-table-in-many-to-many-relationship) – steven7mwesigwa Dec 03 '22 at 06:14

4 Answers4

2

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();
xenooooo
  • 1,106
  • 1
  • 2
  • 8
1

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.

1

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.

Dmitry Leiko
  • 3,970
  • 3
  • 25
  • 42
  • I think your answer is correct but what to write in `DatabaseSeeder.php`, I tried `for($i=1;$i<=50;$i++){ (new CategoryQuestionFactory($i))->create(); }` but it adds 1270 records to Category Question table! – Pouya Dec 07 '22 at 12:29
0

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(),
];
HashtagForgotName
  • 651
  • 1
  • 7
  • 23