Ahmad Badpey
Ahmad Badpey

Reputation: 6612

Eloquent - Get single model when using morphMany in polymorphic relationship

I have a Contact named model like this :

class Contact extends Model
{
    public    $timestamps = false;
    protected $primaryKey = 'contact_id';
    
    protected $fillable = [
        'tel', 'fax', 'email', 'mob', 'address'
    ];

    public function contactable ()
    {
        return $this->morphTo();
    }
}

The above model can belong to some other model, for example House model like this:

class House extends Model
{
    protected $primaryKey = 'house_id';

    public function contact ()
    {
        return $this->morphMany('App\Contact', 'contactable');
    }
}

Each of House can only have one related Contact, but since Contact model can be related to other models, I have to define polymorphic relationships.

Now when I want to get a related Contact model of a specific House model, that is, return an array of Contact (that only have one element) while I want to get it as an simple object model; for example:

public function edit (\App\House $house)
{
    $house = $house->load('contact');
    
    return $house;
    
    return view('admin/pages/house/house-edit', compact('house'));
}

The result is something like this:

{
    "house_id": 6,
    "title": "testا",
    "header": "0f74e9aa891bcc6fb84aa744721d9692.jpg",
    "type": "sara",
    "creator": 1,
    "created_at": "2016-07-26 15:19:31",
    "updated_at": "2016-07-26 15:19:31",
    "contact": [
        {
            "contact_id": 1,
            "tel": "1",
            "fax": "2",
            "email": "3",
            "mob": null,
            "contactable_id": 6,
            "contactable_type": "App\\House"
        }
    ]
}

I try to use first() method on a relation:

public function contact ()
{
    return $this->morphMany('App\Contact', 'contactable')->first();
}

But I'm getting this error:

Call to undefined method Illuminate\Database\Query\Builder::addEagerConstraints()

What's the solution to this problem?

Upvotes: 0

Views: 2435

Answers (3)

Tonoslav
Tonoslav

Reputation: 519

You can use morphOne relationship

public function contact ()
{
    return $this->morphOne('App\Contact', 'contactable');
}

Upvotes: -1

Thomas Van der Veen
Thomas Van der Veen

Reputation: 3226

There is a way to solve this without having to create two functions.

An example could be:

// House.php
public function contact()
{

    return Contact

        ::where('contactable_id', $this->id)

        ->where('contactable_type', 'App\\House')

        ->first();

}

Maybe you will have to change some names.

Hope this helps :)

Edit

The solution above can only be called like so:

$house->contact()

If you wish to use it the 'normal' way ($house->contact->first()) you should remove ->first() at the end of the chain.

Upvotes: 1

thefallen
thefallen

Reputation: 9749

I've been checking to see if someone can give an answer but since no one is, I have a very wild guess that this has some chance of working:

public function contactRelation()
{
    return $this->morphMany('App\Contact', 'contactable');
}

public function contact()
{
    $this->load('contactRelation');

    return $this->contactRelation->first();
}

Basically what I think is you can't call the first() method on the morph relation, so maybe if you make the morph first and then try to call first on the result it might work.

Note that you no longer need $house = $house->load('contact'); in your controller, just try to access the relation like this: $house->contact();.

Upvotes: 1

Related Questions