I have users
table and a followers
table. I’m doing a search to get all the users with a specific keyword, but I want the ones which are followers of the current user to appear first. I can get all the followers id’s in a subquery, so my idea was to do something like this:
SELECT id, name, surname, CASE WHEN id IN (SELECT followable_id FROM followers WHERE followable_id = $currentUserId --this is a variable) THEN 1 ELSE 0 END AS friend FROM users ORDER BY friend WHERE name = 'keyword';
I’ve been trying to get this in my Laravel controller, but I can’t find the way. How could I use this SQL select in my Laravel controller? How could translate this SQL code to the Laravel Database Query Builder?
What I have already tried:
Following @Bassel Hossam answer, I wrote the following code:
$placeholders = str_repeat ('?,', count($friendsId) - 1) . '?'; $orderedMachingUsers = User::whereIn('id', $matchingUsersId)->select( [ '*', DB::raw('CASE WHEN id IN ('. $placeholders .') THEN 1 ELSE 0 END AS friend', $friendsId)] ) ->orderByRaw('friend') ->cursorPaginate(9);
It seems very very close, but I’m still geting a “SQLSTATE[HY093]: Invalid parameter number” error. The generated SQL is the following:
SQLSTATE[HY093]: Invalid parameter number select *, CASE WHEN id IN (3, 4, 7, 8, 9, 10, 111, 112, 113, 114) THEN 1 ELSE 0 END AS friend from `users` where `id` in ( 115, 116, 117, 118, 119, 120, 121, 122, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? ) order by friend limit 10
It seems that somehow it’s always adding the same number of question marks than the number of question marks generated in the $placeholders variable. What I can’t understand is why its generating it in an array that I think that should only be related to $matchingUsersId.
dd($matchingUsersId, $friendsId) is returning the following:
array:7 [▼ 0 => array:1 [▼ "id" => 3 ] 1 => array:1 [▼ "id" => 4 ] 2 => array:1 [▼ "id" => 7 ] 3 => array:1 [▼ "id" => 8 ] 4 => array:1 [▼ "id" => 9 ] 5 => array:1 [▼ "id" => 10 ] 6 => array:1 [▼ "id" => 111 ] ] array:5 [▼ 0 => array:1 [▼ "id" => 3 ] 1 => array:1 [▼ "id" => 113 ] 2 => array:1 [▼ "id" => 112 ] 3 => array:1 [▼ "id" => 114 ] 4 => array:1 [▼ "id" => 115 ] ]
Finall working code based on @Bassel Hossam answer:
$placeholder = str_repeat ('?,', count($friendsId) - 1) . '?'; $orderedMachingUsers = User:: whereIn('id', $matchingUsersId)->selectRaw( '*, CASE WHEN id IN ('. $placeholder .') THEN 1 ELSE 0 END AS friend', $friendsId) ->orderByRaw('friend DESC') ->simplePaginate(9);
Advertisement
Answer
the syntax for in
condition should be like CASE WHEN id IN (?,?,?) THEN
so you need to add ?
with the count of $friendsId
so you should use the following
$placeholders = str_repeat ('?,', count($friendsId) - 1) . '?'; $orderedMachingUsers = DB::table('users') ->whereIn('id', $matchingUsersId)->selectRaw( '*, CASE WHEN id IN ('. $placeholder .') THEN 1 ELSE 0 END AS friend', $friendsId) ->orderByRaw('friend') ->get();