phplaraveleloquentlaravel-query-builder

Using whereIn method to return multiple results for the same array value but at different index


$pidArray contains product ID's, some of those product ID's can be the same. I.E: 34 34 56 77 99 34. As is, it appears the whereIn method does not return results for a productId it has already found in $pidArray, even if it has a different index.

 $productDataForOrder = Product::whereIn('id', $pidArray)->get(['id','price']);


 $totalAmount = $productDataForOrder->sum('price');

$productDataForOrder now contains product data, but only for unique ProductID's in $pidarray. So when sum function is run, the sum is wrong as it does not take into account the price for multiple instances of the same productID.

The following code also does not return objects for every product ID in the array which are the same. So if $pidArray contains three identical product ID's, the query will only return a collection with one object, instead of three.

   $query = Product::select();
        foreach ($pidArray as $id)
        {
            $query->orWhere('id', '=', $id);
        }

        $productDataForOrder = $query->get(['id','price']);

        $totalAmount = $productDataForOrder->sum('price');

Solution

  • You're not going to be able to get duplicate data the way that you're trying. SQL is returning the rows that match your where clause. It is not going to return duplicate rows just because your where clause has duplicate ids.

    It may help to think of it this way:

    select * from products where id in (1, 1)
    

    is the same as

    select * from products where (id = 1) or (id = 1)
    

    There is only one record in the table that satisfies the condition, so that is all you're going to get.

    You're going to have to do some extra processing in PHP to get your price. You can do something like:

    // First, get the prices. Then, loop over the ids and total up the
    // prices for each id.
    
    // lists returns a Collection of key => value pairs.
    // First parameter (price) is the value.
    // Second parameter (id) is the key.
    $prices = Product::whereIn('id', $pidArray)->lists('price', 'id');
    
    // I used array_walk, but you could use a plain foreach instead.
    // Or, if $pidArray is actually a Collection, you could use
    // $pidArray->each(function ...)
    $total = 0;
    array_walk($pidArray, function($value) use (&$total, $prices) {
        $total += $prices->get($value, 0);
    });
    
    echo $total;