1

I have two models with many to many relationship, and I did join them with a model with a third table.

What is the best way to insert dummy data into the third table without getting sql error for breaking constraints about foreign key chicks? Is there a way to use the same data that already exists within the the first two tables?

I have these two tables:

class CreateLessonsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('Lessons', function (Blueprint $table) {
            $table->id();
            $table->unsignedBigInteger('user_id');
            $table->string('title', 100);
            $table->text('body');
            $table->timestamps();

            $table->foreign('user_id')
            ->references('id')
            ->on('users')
            ->onDelete('cascade');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('Lessons');
    }
}

The second:

class CreateTagsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('tags', function (Blueprint $table) {
            $table->id();
            $table->string('name', 50);
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('tags');
    }
}

and the "join" third table:

class CreateLessonTagsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('lesson_tags', function (Blueprint $table) {
            $table->id();
            $table->unsignedBigInteger('lesson_id');
            $table->unsignedBigInteger('tag_id');


            $table->foreign('lesson_id')->references('id')->on('lessons')->onDelete('cascade');
            $table->foreign('tag_id')->references('id')->on('tags')->onDelete('cascade');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('lesson_tags');
    }
}

Thanks in advance

  • Just to be clear - you have [set up the many-to-many relationships](https://laravel.com/docs/7.x/eloquent-relationships#many-to-many)? – Don't Panic Apr 16 '20 at 10:23

3 Answers3

1

In the simple way

for($i =0;$i<100 ; $i++)
{
    DB::table('lesson_tags')->insert(
        [
        'lesson_id' => Arr::random(DB::table('Lessons')->pluck('id')->toArray()),
         'tag_id' => Arr::random(DB::table('tags')->pluck('id')->toArray())
         ]
    );
}
0

You can use eloquent ORM like this

first you need to declare a relation in tag and lesson Models:

in Tag Model

  public function lessons()
  {
       return $this->belongsToMany('App\Lesson');
  }

in Lesson Model

 public function tags()
 {
      return $this->belongsToMany('App\Tag');
 }

then you can use this in loop for example

$Lesson = new Lesson();
$Lesson->user_id = ....
...
$Lessons->save();

$tag = new Tag();
$tag->name ='';

$Lessons->tags()->save($tag)
0

Efficiently, with three queries only:

$lessonIds = Lesson::pluck('id')->toArray();
$tagIds = Tag::pluck('id')->toArray();

$insert = [];

$relationsAmount = 10;

$now = \Carbon\Carbon::now();

for ($i = 0; $i < $relationsAmount; $i++) {
    $insert[] = [
        'lesson_id' => array_rand($lessonIds),
        'tag_id' => array_rand($tagIds),
        'created_at' => $now,
        'updated_at' => $now,
    ];
}

\DB::table('lesson_tags')->insert($insert);
// if you name your pivot table per Eloquent naming convention (which would be 'lesson_tag' in this case), Laravel will do lot of things for you out of the box
Tpojka
  • 6,996
  • 2
  • 29
  • 39