user10139010
user10139010

Reputation:

Refactor merged query in Laravel

I currently have 2 methods which carry out search queries both ways then they are merged together to retrieve the result.

Model relation

public function linkedTo() {
    return $this->hasMany(Linked::class, 'team_id');
}

public function linkedFrom() {
    return $this->hasMany(Linked::class, 'linked_id');
}

Query

$linkedTo = $team->linkedTo()->with(['games' => function ($query) use ($search) {
    $query->where('title', 'like', "%$search%");
}])->get();

$linkedFrom = $team->linkedFrom()->with(['games' => function ($query) use ($search) {
    $query->where('title', 'like', "%$search%");
}])->get();

$links = $linkedTo->merge($linkedFrom);

To get the result I need from the search results I had to merge these together.

Is there a cleaner way to join these together within one query?

Upvotes: 0

Views: 63

Answers (2)

apokryfos
apokryfos

Reputation: 40683

If you want to reduce code duplication (but not actually change what is executed) you can do this:

$filter = function ($query) use ($search) {
    $query->where('title', 'like', "%$search%");
};
$linkedTo = $team->linkedTo()->with(['games' => $filter ])->get();
$linkedFrom = $team->linkedFrom()->with(['games' => $filter ])->get();
$links = $linkedTo->merge($linkedFrom);

Upvotes: 0

Maarten Veerman
Maarten Veerman

Reputation: 1621

Use union:

// First build the queries, note I removed 'get()'
$linkedTo = $team->linkedTo()->with(['games' => function ($query) use ($search) {
    $query->where('title', 'like', "%$search%");
}]);

$linkedFrom = $team->linkedFrom()->with(['games' => function ($query) use ($search) {
    $query->where('title', 'like', "%$search%");
}]);

// Now union and get the results
$links = $linkedTo->union($linkedFrom)->get();

More details here: https://laravel.com/docs/8.x/queries#unions

Upvotes: 1

Related Questions