Pizzucu
Pizzucu

Reputation: 25

Laravel 8: How to seed a pivot table in many to many relationship

I want to seed my tables via seeder/factory. I want to seed a Pivot table, which connects the tables atg and debtor and is called atg_debtor, which hast an id, created_at, updated_at, atg_id, debtor_id.

When inserting data via Eloquent everything works fine. When I try to seed my db with Seeders/Factory it always tries to insert data to my atg table, which I don´t want. I want to seed the debtor table (that works fine) and the pivot table with a given atg_id and the dynamic debtor_id, which is created whilst seeding the debtor.

My Debtor Model:

<?php

namespace App\Models;

use App\Models\Atg;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;

class Debtor extends Model
{
    use HasFactory;

    public function atg()
    {
        return $this->belongsToMany(Atg::class)->withTimestamps();
    }
}

The DebtorSeeder:

<?php

namespace Database\Seeders;

use App\Models\Atg;
use App\Models\Debtor;
use Illuminate\Database\Seeder;

class DebtorSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        $debitor = Debtor::factory()
                ->count(1)
                ->hasAtg(1)
                ->create();
    }
}

The DebtorFactory:

<?php

namespace Database\Factories;

use App\Models\Debtor;
use Illuminate\Database\Eloquent\Factories\Factory;

class DebtorFactory extends Factory
{
    /**
     * The name of the factory's corresponding model.
     *
     * @var string
     */
    protected $model = Debtor::class;

    /**
     * Define the model's default state.
     *
     * @return array
     */
    public function definition()
    {
        return [
            'created_at' => now(),
            'created_by_id' => '3',
            'rechtsform' => 'Unternehmen',
            'name' => $this->faker->company    
        ];
    }
}

Thank you!

Upvotes: 1

Views: 5360

Answers (3)

Htin Lynn
Htin Lynn

Reputation: 11

You can use hasAttached method to seed pivot table in Laravel 8 In your DatabaseSeeder class file.

Atg::factory()->hasAttached(
               Debtor::factory();
              )
              ->create();

That will help you each Atg create item with dynamic Debtor id in atg_debtor table. But it needs to connect in the model class binding.

class Debtor extends Model
{
  use HasFactory;
    
   public function atg()
   {
      return $this->belongsToMany(Atg::class)->withTimestamps();
   }
 }

Other Methods, You can use Using Magic Methods to create seed data in Pivot Table

Atg::factory()->hasDebtor(1)
              ->create();

Here are the reference methods https://laravel.com/docs/8.x/database-testing#pivot-table-attributes

Upvotes: 0

Peppermintology
Peppermintology

Reputation: 10210

Assuming you're seeding your database tables separately:

// Seed 50 Atg records
Atg::factory(50)->create();

// Seed 4 Debtor records
Debtor::factory(4)->create();

You could override the configure method in your Debtor factory to attach some Atg models once they have been created:

class DebtorFactory extends Factory
{
    public function configure()
    {
        return $this->afterCreating(function (Debtor $debtor) {
            // Once a Debtor record has been created
            // Pick between 1 and 5 Atg records in a random order
            // Associate the Atg and Debtor records
            $debtor->atg()
                   ->attach(Atg::inRandomOrder()->take(random_int(1, 5))->pluck('id'));
        });
    }
}

Upvotes: 2

Miqayel Srapionyan
Miqayel Srapionyan

Reputation: 587

so first you can check if in the database there is Atg, if no you can seed like you do, otherwise you can seed Debtor then save Atg in relations(->atg() is your relation name so improve it if i wrote wrong name) like so:

P.S. Also i removed ->count(1) from Debtor because by default it creates one item.

<?php

namespace Database\Seeders;

use App\Models\Atg;
use App\Models\Debtor;
use Illuminate\Database\Seeder;

class DebtorSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        $atg = Atg::first();
        if($atg){
           $debitor = Debtor::factory()
                ->create();

           $debitor->atg()->save($atg);
        }else {
           $debitor = Debtor::factory()
                ->hasAtg(1)
                ->create();
        }
    }
}

Upvotes: 2

Related Questions