Method 1
Perhaps the best solution would be to use Collection
of Laravel, since you are bringing everything with get
.
In version 5.5 of Laravel you could use firstWhere
to do this by iterating over $ids
by getting the values according to their position:
Example:
foreach ($ids as $id) {
$produto = $produtos->firstWhere('id', '=', $id);
}
Method 2
What's more, you could use sortBy
to sort products:
$sorter = static function ($produto) use ($ids) {
return array_search($produto->id, $ids);
};
$produtos = Produtos::whereIn('id', $ids)->get()->sortBy($sorter);
In this second example, array_search
will return the position of the array
where the id
is, causing the order to be according to the $ids
position.
See the documentation for array_search
Note : In this second example I did not test, but you probably want to use sortByDesc
instead of sortBy
.
Method 3
Depending on the situation you are going to use this, it may still be worthwhile to use the lists
method, combined with the iteration in $ids
$produtos = Produto::whereIn('id', $ids)->lists('nome', 'id');
foreach ($ids as $id) {
if (isset($produto[$id]) {
echo $produto[$id];
}
}
Method 4
I think this is best applied to you. I did a search on Collection documentation and found this beauty called keyBy
.
Basically what it does is to transform the indexes of the Collection according to the last key. In this case I choose id
.
See!
$produtos = Produto::whereIn('id', $ids)->get()->keyBy('id');
So you could do something similar to the method 3 operation explained above, but $produtos[$id]
would give you access to the Produto
object, instead of just the name itself. >
Method 5
A asks in SOEN also that there is the same questioning as yours. I particularly did not like the way it was done, but it would be basically this:
$rawOrder = DB::raw(sprintf('FIELD(id, %s)', implode(',', $ids)));
$produtos = Produto::whereIn('id', $ids)
->orderByRaw($rawOrder)
->get();
Note that you use implode
with a comma to generate a snippet of an SQL query through DB::raw
. That way, however much I find it aesthetically ugly to do so, I have to admit that it is better that the ordering already comes from the bank, than having to reprocess everything with PHP.
FIELD
aims to determine the order that ORDER BY
should consider when sorting through the ID
field. That is, the query executed in the database will be exactly:
SELECT * FROM produtos ORDER BY FIELD(id, 12, 5, 1, 8, 16);