Sallu
Sallu

Reputation: 489

Laravel - Merge Two Relationship gives an error

Using Laravel 5.4, I have a table Teams and another table Matches Each match has TEAM HOME ID and TEAM AWAY ID

I found this great trick to merge in such cases to find all the matches played by a team either at home or away. But it does not seem to work.

Laravel merge reltationships

/**
 * The matches that this team has played at home.
 */
public function matchesHome()
{
    return $this->hasMany('App\Match', 'team_home_id', 'id');
}

/**
 * The matches that this team has played away.
 */
public function matchesAway()
{
    return $this->hasMany('App\Match', 'team_away_id', 'id');
}

/**
 * The matches that this team has played.
 */
public function matches()
{
    $matchesPlayedHome = $this->matchesHome();
    $matchesPlayedAway = $this->matchesAway();

    // Merge collections and return single collection.
    return $matchesPlayedHome->merge($matchesPlayedAway);     // cannot get this to work | Call to undefined method Illuminate\Database\Query\Builder::merge()
}

The error I am getting is Call to undefined function merge Call to undefined method Illuminate\Database\Query\Builder::merge()

Please help Thanks

..................

I have even tried eager loading, in that case the error becomes

Relationship method must return an object of type Illuminate\Database\Eloquent\Relations\Relation

public function matches()
{
    $matches = Team::with('matchesHome', 'matchesAway')->get();
    return $matches;
}

Upvotes: 2

Views: 3211

Answers (2)

Sallu
Sallu

Reputation: 489

This is how I solved the problem. The $appends answer in another post was not clear so let me explain below.

If you don't add any method to $appends, Laravel thinks that it is also a relationship attribute and gives an error Relationship method must return an object of type Illuminate\Database\Eloquent\Relations\Relation

Because it is looking for a relationship which it does not get. That is why if we add $appends we can have this following code working.

If anyone lands in this situation this is how I solved it.

protected $appends = ['matches'];

/**
 * The matches that this team has played at home.
 */
public function matchesHome()
{
    return $this->hasMany('App\Match', 'team_home_id', 'id');
}

/**
 * The matches that this team has played away.
 */
public function matchesAway()
{
    return $this->hasMany('App\Match', 'team_away_id', 'id');
}


/**
 * This function is used by the appends to append two attributes
 */
public function getMatchesAttribute()
{
    return $this->matchesHome->merge($this->matchesAway);
}

We can also replace this with Eager loading and it will work fine.

Upvotes: 2

Borjante
Borjante

Reputation: 10517

I think your syntax is a bit off:

function matches() {
  return $this->matchesHome->merge($this->matchesAway);
}

Upvotes: 0

Related Questions