aronccs
aronccs

Reputation: 294

Laravel Seed Multiple Relations

I have 3 models: Member, Invoice and Payment

Here is the Member model:

class Member extends Model
{
     public function invoice()
     {
          return $this->hasOne(Invoice::class);
     }
}

And in the Invoice model:

class Invoice extends Model
{
     public function member()
     {
        return $this->belongsTo(Member::class, 'member_id');
     }

     public function payments()
     {
        return $this->hasMany(Payment::class, 'invoice_id');
     }
}

And lastly, the Payment model:

class Payment extends Model
{
     public function invoice()
     {
          return $this->belongsTo(Invoice::class, 'invoice_id');
     }
}

Now, in my seeder, I want to create a Payment for each Invoice of each Member:

public function run()
{
   factory(Member::class, 100)->create()->each(function ($m) {
       $m->invoice()->save(factory(App\Invoice::class)->create()->each(function ($i) {
           $i->payments()->save(factory(App\Payment::class)->make());
     }));
  });
}

But it returns an error when I try to seed:

Symfony\Component\Debug\Exception\FatalThrowableError  : Type error: Argument 1 passed to Illuminate\Database\Eloquent\Relations\HasOneOrMany::save() must be an instance of Illuminate\Database\Eloquent\Model, boolean given

How can I achieve my desired output?

Upvotes: 1

Views: 2890

Answers (2)

mirsahib
mirsahib

Reputation: 445

In you seed/Databaseeder.php (tested in Laravel 7)

public function run()
    {
        factory(App\Member::class, 100)->create()->each(function ($m) {
            // Seed the relation with one address
            $invoice = factory(App\Invoice::class)->make();
            $payments = factory(App\Payment::class,5)->make();
            $m->invoice()-save($invoice);
            $invoice->payments()->saveMany($payments)
        });
    }

The run function represent create 100 instance of member model for each member model create one invoice model and for each invoice create 5 payments model

Upvotes: 0

prateekkathal
prateekkathal

Reputation: 3572

Refer - Factory Callbacks and saveMany function

Now, In your MemberFactory.php, add this

$factory->afterCreating(App\Member::class, function ($member, $faker) {
  $member->invoice()->save(factory(App\Invoice::class)->make());
});

In you InvoiceFactory.php, add this

$factory->afterMaking(App\Invoice::class, function ($invoice, $faker) {
  $invoice->payments()->saveMany(factory(App\Payment::class, 5)->make());
});

Finally, in your run() function, do

public function run()
{
  factory(Member::class, 100)->create();
}

Haven't tested, but should work :)

Also, I don't think you need the second parameters in your relation. The function should automatically be able to get the foreign key match if you are using singular nomenclature.

Upvotes: 3

Related Questions