Laravel 8 Multiple Relationships for Factory

wizardzeb picture wizardzeb · Sep 10, 2020 · Viewed 11.6k times · Source

In Laravel 8 it is possible to quickly fill relationships with factories. However, I cannot figure out how to generate more than one relationship. How can I create a random or new relationship for each link using the new Laravel 8 syntax?

This factory syntax is only available in Laravel 8. https://laravel.com/docs/8.x/database-testing#factory-relationships

Problem

Consider the following relationship:

  • Each link belongs to a website and a post.
  • Both websites and posts can have many links.
<?php

class Post extends Model
{
    use HasFactory;

    function links()
    {
        return $this->hasMany(Link::class);
    }
}

class Website extends Model
{
    use HasFactory;

    function links()
    {
        return $this->hasMany(Link::class);
    }
}

class Link extends Model
{
    use HasFactory;

    function post()
    {
        return $this->belongsTo(Post::class);
    }

    function website()
    {
        return $this->belongsTo(Website::class);
    }
}


What I tried/want

What I tried below will only generate one model for all the links. How can I create a random or new relationship for each link using the new Laravel 8 syntax?

Link::factory()->count(3)->forPost()->forWebsite()->make()

=> Illuminate\Database\Eloquent\Collection {#4354
     all: [
       App\Models\Link {#4366
         post_id: 1,
         website_id: 1,
       },
       App\Models\Link {#4395
         post_id: 1, // return a different ID
         website_id: 1,
       },
       App\Models\Link {#4370
         post_id: 1, // return a different ID
         website_id: 1, // return a different ID
       },
     ],
   }

Answer

Andriy Lozynskiy picture Andriy Lozynskiy · Feb 21, 2021

Just add this to your LinkFactory:

  public function definition()
  {
    return [
        'post_id' => function () {
            return Post::factory()->create()->id;
        },

        .....
    ];
}

And now you can create new Post for each new Link:

Link::factory()->count(3)->create();//Create 3 links with 3 new posts

or attach new Links to existing Post:

Link::factory()->count(3)->create(['post_id' => Post::first()->id]); //create 3 links and 0 new posts