Reputation: 294
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
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
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