Home > Software design >  One to Many relationship using custom primary keys
One to Many relationship using custom primary keys

Time:05-01

I have 3 tables: User (id: Primary Key), Recruiter(user_id: Primary & Foreign Key) and Company(id: Primary Key). What happens is that the Recruiter is just a User with some other columns and basically he is the one interacting with the application.

Since there can only be one Recruiter associated with the User table I have decided to use the user_id as both a FK and PK. Between the Company and Recruiter there is a One to Many relationship where one company can have many recruiters.

I'm trying to associate the recruiter with a company but I'm not being able to do so.

I'm using tinker trying to implement the functions. What I do basically is

$recruiter->company()->associate($company)
$recruiter-> save;

I get true as output as well as

App\Models\Recruiter {#4536
     user_id: 4,
     created_at: "2022-04-30 18:07:25",
     updated_at: "2022-04-30 18:07:25",
     company_id: null,
     company: App\Models\Company {#4544
       id: 1,
       created_at: "2022-04-30 17:48:48",
       updated_at: "2022-04-30 17:48:48",
       name: "Apple",
       company_image: "apple.png",
       short_description: "Electronics company",
       long_description: "Long description for electronics company",
       email: "[email protected]",
       establishment_year: "1950-01-01",
       website_url: "www.apple.com",
       location: "United States of America",
       followers_count: 0,
       company_size: 0,
     },
   }

As you can see the company somehow gets associated but the company_id is not updated. These are the Models

User

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;

class User extends Model
{
    
    use HasApiTokens, HasFactory, Notifiable;

    public function recruiter() 
    {
        return $this->hasOne('App\Models\Recruiter');
    }
}
 

Recruiter

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Recruiter extends Model
{
    use HasFactory;
    
    public function user()
    {
        return $this->belongsTo('App\Models\User');
    }

    public function company()
    {
        return $this->belongsTo('App\Models\Company', 'company_id', 'user_id');
    }
}

Company

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Company extends Model
{
    use HasFactory;

    public function recruiters() 
    {
        return $this->hasMany('App\Models\Recruiter', 'company_id', 'user_id');
    }
}

CodePudding user response:

Company relation on recruiter model has a bug:

Instead of:

public function company()
{
    return $this->belongsTo('App\Models\Company', 'company_id', 'user_id');
}

it should be

public function company()
{
    return $this->belongsTo('App\Models\Company', 'company_id', 'id'); //or return $this->belongsTo('App\Models\Company', 'company_id');
}

BelongsTo relationship syntax is

return $this->belongsTo(ParentModel::class, 'foreign_key', 'owner_key');

where

foreign_key is the foreign id column on the child model/table ('company_id' on recruiters table in this case).

owner_key is the primary key or the reference column on the parent model/table ('id' column on companies table in this case)

The problem you were having was because there was no 'user_id' column on companies table.

Further reference: https://laravel.com/docs/9.x/eloquent-relationships#one-to-one-defining-the-inverse-of-the-relationship

  • Related