Search code examples
laravellaravel-5laravel-5.5faker

How to add Relationship of Factories to faker in Laravel


I have models like this:

Entity - entities table
Address - address table
User - users table
Geoloc - geoloc table
UserEntity - entity_user table

Now Entity can have one address and one geoloc, but it can have multiple users this is what UserEntity is for.

So I need to do a pattern where factory will create it like this:

User>Entity>Address>Geoloc>UserEntity

so when user is created it will also create entity, address and geoloc, associate entity id to address, associate geoloc id to entity and insert user_id and entity_id to user entity.

Here's my current setup:

AddressFactory:

$factory->define(App\Address::class, function (Faker $faker) {
    return [
        'building_name' => $faker->company,
        'address' => $faker->streetAddress,
        'town' => $faker->city,
        'postcode' => $faker->postcode,
        'telephone' => $faker->phoneNumber,
        'private' => $faker->boolean($chanceOfGettingTrue = 50),
        'entity_id' => function () {
            return factory(App\Entity::class)->create()->id;
        }
    ];
});

EntityFactory:

factory->define(App\Entity::class, function (Faker $faker) {
    return [
        'name' => $faker->unique()->company,
        'type' => 'Service',
        'tags' => 'mens clothes, online shopping, ladies clothes',
        'email' => $faker->safeEmail,
        'logo' => $faker->imageUrl($width = 640, $height = 480),
        'cover' => $faker->imageUrl($width = 1000, $height = 600),
        'bio' => $faker->catchPhrase,
        'main' => $faker->realText($maxNbChars = 200, $indexSize = 2),
        'twitter_business' => 'OfficialOAFC',
        'facebook_business' => 'MolinoLounge',
        'instagram_business' => 'OfficialOAFC',
        'google_places' => 'ChIJvaCBHYG3e0gRfhs0xZ1TBB8',
        'eventbrite' =>'8252340832',
        'featured' => $faker->boolean($chanceOfGettingTrue = 50),
        'url' => $faker->url,
        'video' => '6R2DIFySho4',
        'wikipedia' => 'Hackerspace',
        'contact_name' => $faker->name,
        'contact_number' => $faker->phoneNumber,
        'geoloc_id' => function () {
            return factory(App\Geoloc::class)->create()->id;
        }
    ];
});

UserFactory:

$factory->define(App\User::class, function (Faker $faker) {
    static $password;
    return [
        'name' => $faker->name,
        'email' => $faker->unique()->safeEmail,
        'password' => $password ?: $password = bcrypt('secret'),
        'avatar' => $faker->imageUrl($width = 640, $height = 480),
        //'telephone' => $faker->phoneNumber,
        'role' => rand(1, 2),
        'remember_token' => str_random(10),
    ];
});

DatabaseSeeder:

    factory(App\User::class, 30)->create();
    factory(App\Address::class, 30)->create();

User relations:

public function entities()
{
    return $this->belongsToMany('App\Entity', 'entity_user', 'user_id', 'entity_id');
}

Entity relations:

public function address()
{
    return $this->hasOne('App\Address', 'entity_id');
}
public function _geoloc()
{
    return $this->belongsTo('App\Geoloc', 'geoloc_id', 'id');
}

Solution

  • I think you can achieve this in your seeder like:

    factory(App\User::class, 30)->create()->each(function($user) {
    
        $entity = factory(App\Entity::class)->make();
    
        $address = factory(App\Address::class)->create([
            'entity_id' => $entity
        ]);
    
        $user->entities()->save($entity);
    });
    

    If you are going to create multiple entities for each user, you will need to use saveMany() instead of save().