Laravel Parties relationship

Solution:

I believe you mean the Party can either belong to the People model or the Company model, and not both. If this is true, then use a polymorphic One to Many relationship.

Laravel Docs: https://laravel.com/docs/8.x/eloquent-relationships#one-to-many-polymorphic-relations

Company

Note: the protected $with attribute makes sure the Party always loads with the object.

class Company extends Model
{
    protected $with = ['party'];

    public function party()
    {
        return $this->morphMany(Party::class,'object');
    }
}

People Model

Note: the protected $with attribute makes sure the Party always loads with the object.

class People extends Model
{
    protected $with = ['party'];

    public function party()
    {
        return $this->morphMany(Party::class,'object');
    }
}

Party Model

You would then have an ‘object’ relationship on the Party model so that $party->object get’s either the People or the Company. I recommend using the ‘object’ relationship instead of the ‘people’ and ‘company’ relationships since all models would have either one or the other, but I included both here in case you wanted it.

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

    public function people()
    {
        return $this->belongsTo(People::class,'object_id')->where('object_type','=',People::class);
    }

    public function company()
    {
        return $this->belongsTo(Company::class,'object_id')->where('object_type','=',Company::class);
    }
}

Now you can use $party->object, or $party->people and $party->company to get the Person or Company it belongs to.

$party->object; // Either Company or People object
$party->people; // People object, would fail if the party belongs to Company
$party->company; // Company object, would fail if the party belongs to People 

Now when you get the People or Company object, it should include the Party automatically.

Route::get('/people', function () {
    $people = new People();
    return $people->get()->toArray();
});

As noted above, the $with attributes ensures the party is loaded each time automatically. If you’d prefer to not load the party every time, remove the $with attribute and load it after.

Route::get('/people', function () {
    $people = new People();
    return $people->with('party')->get()->toArray();
});