Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel Eloquent relationship between one Model and Many Models as MorphOne?

Introduction:

I have these Tables with their Models:

  • addresses table --> Address model
  • users table --> User model
  • companies table --> Company model
  • properties table --> Property model

Rules:

  • each User can have one address only.
  • each Company can have one address only.
  • each Property can have one address only.

Two possible relationships planning could be done here:

  • User hasOne Address and Address belongsTo User [i.e. one-to-one relationship] but the disadvantage is that the foreign key here is located in addresses table i.e. user_id field and by repeating the same relationship with other models [Company and Property] we will get another two foreign keys in the addresses table which are [company_id and property_id], then we will end up with 3 foreign keys for 3 Models But only one will be filled by each row record leaving always two foreign keys fields left empty

    I feel this is an overhead charge to addresses table.

OR the other way around:

  • Address hasOne User and User belongsTo Address [one-to-one relationship also]. This has the advantage that it keeps the foreign key here in the related Model i.e. [User, Company and Property] this way there is no empty fields of foreign keys --- But still this is against the real life Modelling logic which dictates that User hasOne Address more than Address hasOne User.

My Question:

Is there any other relationship that can bind these 4 Models in one relationship similar to Polymorphic Relations but without using MorphMany but instead using MorphOne which strangely enough, I can not find it in the Documentation of Laravel although the method itself exists in Eloquent Relations.

Is this MorphOne polymorphic relation possible and how it is composed?

Existing code:

//Address model
public function user(){
    return $this->hasOne(User::class);
}
public function company(){
    return $this->hasOne(Company::class);
}
public function property(){
    return $this->hasOne(Property::class);
}

//User model
public function address(){
    return $this->belongsTo(Address::class);
}

//Company model
public function address(){
    return $this->belongsTo(Address::class);
}
//Property model
public function address(){
    return $this->belongsTo(Address::class);
}
like image 457
WillKoz Avatar asked Jun 11 '18 03:06

WillKoz


1 Answers

Here is the MorphOne relationship between Address on one side and User, Company and Property on the other-side:

class Address extends Model
    public function addressable(){
        return $this->morphTo();
    }       
}

class User extends Model
    public function address(){
        return $this->morphOne(Address::class,'addressable'); //note this is not MorphMany()
    }       
}

class Company extends Model
    public function address(){
        return $this->morphOne(Address::class,'addressable');
    }       
}

class Property extends Model
    public function address(){
        return $this->morphOne(Address::class,'addressable');
    }       
}

then in the UserController something like that:

$user = User::find(1);

$addressData = [
    'street_name' => '5, Golf street',
    'country_id' => 100, //etc..
];

//to add new address record related to user:
$user->address()->create($addressData);
dd($user->address);

//to update existing address record related to user:
$user->address->update($addressData);
//dd($user->address);
like image 164
WillKoz Avatar answered Nov 08 '22 11:11

WillKoz