Chetan Chitte
Chetan Chitte

Reputation: 147

Factory model relationships in Laravel

I have 2 tables named Users and Users_meta. Both are sharing One-To-One relationship. I would like to insert dummy data with the help of seeding. I am able to do that, the only thing that is driving me crazy is that, I am unable to establish relationship between users and users_meta table with user_id as foreign key. I tried few ways but that either creates duplicate entires with same user_id or keeps repeating the same user_id.

What exactly I would like is; when creating for example 100 records, after first user record insertion, it should take the same user's user_ID, add it to users_meta table's user_id field and repeat the insertion till 100 fake records.

Any help on this would be greatly appreciated

Code in : UserFactory.php

$factory->define(App\User::class, function (Faker $faker) {
static $password;

return [
    'username' => $faker->userName,
    'email' => $faker->unique()->safeEmail,
    'password' => $password ?: $password = bcrypt('secret'),
    'referral_code' => str_random(10),
    'referred_by_code' => str_random(10),
    'role'  => $faker->randomElement(['administrator', 'user', 'volunteer']),
    'remember_token' => str_random(10),
]; });

Code in : UsersMetaFactory.php

$factory->define(App\Usersmeta::class, function (Faker $faker) {

return [
    'user_id'   =>  $faker->randomElement(\App\User::pluck('id')->toArray()),
    'first_name' => $faker->firstname,
    'last_name' => $faker->lastname,
    'gender' => $faker->randomElement(['male', 'female']),
    'date_of_birth' =>  $faker->dateTimeThisCentury->format('Y-m-d'),
    'address'   =>  $faker->address,
    'city'  =>  $faker->city,
    'state' =>  $faker->state,
    'zip_code'  =>  $faker->postcode,
    'country'   =>  $faker->country,
    'cell_phone'    =>  $faker->e164PhoneNumber,
    'bitcoin_address' => str_random(16),
    'monero_address'    =>  str_random(16),
    'security_question' =>  $faker->realText($maxNbChars = 20, $indexSize = 2),
    'security_answer'   =>  $faker->realText($maxNbChars = 40, $indexSize = 2),
    'is_founder'    =>  $faker->boolean($chanceOfGettingTrue = 50),
    'status'    =>  $faker->randomElement(['active', 'inactive']),
    'terms' =>  $faker->boolean
]; });

The randomElement() method gives me random id which violates one to one relationship principal and my app breaks down. I would like it should fetch id from users table and pass the same id as user_id to users_meta table and continue generating fake records.

CreateUsersTable migration class

public function up()
{
    Schema::create('users', function (Blueprint $table) {
        $table->increments('id');
        $table->string('username')->unique();
        $table->string('email')->unique();
        $table->string('password');
        $table->string('referral_code')->unique();
        $table->string('referred_by_code');
        $table->enum('role', ['administrator', 'user', 'volunteer'])->nullable();
        $table->rememberToken();
        $table->timestamps();
    });
}

CreateUsersMetaTable migration class

public function up()
{
    Schema::create('users_meta', function (Blueprint $table) {
        $table->increments('id');
        $table->integer('user_id')->unsigned();
        $table->foreign('user_id')->references('id')->on('users');
        $table->string('first_name');
        $table->string('last_name');
        $table->enum('gender', ['male', 'female'])->nullable();
        $table->string('date_of_birth')->nullable();
        $table->string('address')->nullable();
        $table->string('city')->nullable();
        $table->string('state')->nullable();
        $table->string('zip_code')->nullable();
        $table->string('country');
        $table->string('cell_phone');
        $table->string('bitcoin_address')->nullable();
        $table->string('monero_address')->nullable();
        $table->string('security_question');
        $table->string('security_answer');
        $table->string('is_founder')->nullable();
        $table->enum('status', ['active', 'inactive'])->nullable();
        $table->string('terms');
        $table->timestamps();
    });
}

public function down()
{
    Schema::dropIfExists('users_meta');
    Schema::enableForeignKeyConstraints();
}

Upvotes: 1

Views: 2435

Answers (1)

Alexey Mezenin
Alexey Mezenin

Reputation: 163758

You should remove this line:

'user_id' => $faker->randomElement(\App\User::pluck('id')->toArray()),

And use relationship when creating a new model. Here's a modified example from the docs:

factory(App\User::class, 50)->create()->each(function ($u) {
    $u->usersmeta()->save(factory(App\Usersmeta::class)->make());
});

Upvotes: 1

Related Questions