Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

vincej's avatar
Level 15

How to Sum Two Different Arrays

I have two different arrays, no big deal, except that one is an array of objects the other a straight array.

So here is one:

$allocation = {array} [4]
 0 = {stdClass} [2]
  inv_product_id = 123
  allocated = "4"
 1 = {stdClass} [2]
  inv_product_id = 789
  allocated = "8"

etc etc

Here is the other:

$orders = {array} [6]
 123 = "131"
 789 = "12"

etc etc

So, the objective is sum $allocation values ie allocated together with the $orders value. So, in this example, for product code 123, the sum total would be 135.

I have been trying to convert $allocation into the same format as $orders without success. My belief has been that once they are in the same format, then summing them should not be too bad. But I have not gotten that far yet. Most of my efforts have revolved around using foreach loops or for loops and array_push

I have looked carefully at the Laravel helpers but nothing has worked for me yet.

Any ideas would be really welcome, as I have been beating my head over this.

Many thanks !

0 likes
52 replies
jlrdw's avatar

Can you convert object to array using toArray() and see if php array_sum would work.

Usage

$dog = Dog::select('dogname', 'comments')
                ->where('dogid', '<', $dogid)
                ->get()
                ->toArray();

Just example.

vincej's avatar
Level 15

Thanks for that. Ok, I will give it a go. I had not thought of that. The collection that comes in from my query is not shown, however it was converted toArray, albeit inside Laravel.

vincej's avatar
Level 15

Tried your suggestion and it still produces an array of objects like above. Thanks though.

vincej's avatar
Level 15

No, I am not working in JS. The allocation array is returned by a query. The orders array is returned by using the following:

 $id = $request->get('product_id');  // GRAB DATA FROM POST ARRAY
 $qty = $request->get('quantity');

$orders = [];
$orders = array_combine($id,$qty);

jlrdw's avatar

At the end of the allocation query after ->get(), Changing to ->get()->toArray(); Should work.

vincej's avatar
Level 15

Yes, You suggested that as given above. I tried it and the result is still an array of objects, as given above.

Query:

public function allocation($ref){
       return DB::table('inventory')
            ->join('quotations','product_id','=','inventory.inv_product_id')
            ->select('inv_product_id',DB::raw('SUM(allocated) as allocated' ))
            ->where('quotations.reference','=',$ref)
            ->groupBy('inv_product_id')
            ->get()
            ->toArray();
    }

Controller code:

 $inventory = new Inventory();
  $allocation = $inventory->allocation($ref);

jlrdw's avatar

May be a boo boo, but eloquent is what I am using:

$dogs = Dog::where('adopted', '=', 0)->get()->toArray();
        echo '<pre>';
        var_dump($dogs);
        echo '</pre>';
        exit();        

Gives:

array(14) {
  [0]=>
  array(7) {
    ["dogid"]=>
    int(91)
    ["dogpic"]=>
    string(12) "dallas77.jpg"
    ["dogname"]=>
    string(6) "Dallas"
    ["sex"]=>
    string(1) "M"
    ["comments"]=>
    string(227) "2 year lab shepard mix. Gets along well with some dogs, but not dominate dogs. Protective of his area, but once he knows you he loves play time. He has played fine with some puppies we've had. Better suited for only dog family."
    ["adopted"]=>
    int(0)
    ["lastedit"]=>
    string(19) "2016-09-18 17:44:31"
  }
  [1]=>
  array(7) {
    ["dogid"]=>
    int(192)
    ["dogpic"]=>
    string(12) "danny173.jpg"
    ["dogname"]=>
    string(5) "Danny"
    ["sex"]=>
    string(1) "M"
    ["comments"]=>
    string(193) "1 year, I was here as a puppy and I was adopted.  My new family couldn't take care of me, please be my new forever family. It takes me a while to get used of other pets, so please work with me."
    ["adopted"]=>
    int(0)
    ["lastedit"]=>
    string(19) "2016-03-19 17:29:00"
  }
  [2]=>
/////more

I am going to have to figure out why it doesn't in query builder also.

Let's see if @cronix knows? He is good with this array stuff.

I would think that orm and qb would return same type results.

vincej's avatar
Level 15

I don't know either. I have to use QB in order to create the SUM in the query. It doesn't exist in Eloquent. I would post an image from PHPStorm, but I don't know how to post images in mark down.

I am trying a different approach, trying to create a whole new query which will sum the records from the two different tables. No success yet.

jlrdw's avatar

@VINCEJ - Eloquent has all query builder methods, you could try that.

vincej's avatar
Level 15

Ok, I see it now, "You may also use the count, sum, max, and other aggregate methods provided by the query builder. These methods return the appropriate scalar value instead of a full model instance:"

I guess I use QB because I am old school. :o)

jlrdw's avatar

You could write a regular query as example:

$sql = "SELECT dc_pets.ownerid, dc_pets.petowner, COUNT(petid) AS total FROM dc_pets ";
$sql .= "WHERE dc_pets.ownerid IS NOT NULL AND dc_pets.ownerid > 0 GROUP BY dc_pets.ownerid";

        $sth = DB::getPdo()->prepare($sql);
        $sth->execute();
        $quy = $sth->fetchAll(\PDO::FETCH_ASSOC);

The PDO::FETCH_ASSOC would work. Just an example I had from a while back.

Can also bind parameters.

vincej's avatar
Level 15

Thanks for that. That makes me smile. How many people in today's world would understand your query. :o)

jlrdw's avatar

The funny part is eloquent converts to regular queries just like that at runtime.

I'm on mobile now I will also a little later post a good example of using the DB facade, from cronix.

vincej's avatar
Level 15

I have almost got my query right, but not quite. I need to be able to sum orders and allocated as Total. Any ideas ? Maybe a subquery?? How in the heck do you do one of those on QB ? Many thanks.

 public function customer_order($id) {
        return DB::table('orders')
            ->join('inventory', 'inv_product_id', '=', 'orders.product_id')
            ->select( 'orders.product_id', 'orders.quantity as orders',  DB::raw('SUM(inventory.allocated) as allocated'))
            ->where('orders.reference',   '=', $id)
            ->groupBy('orders.product_id')
            ->get();

jlrdw's avatar

See last reply, last example here,

https://laracasts.com/discuss/channels/guides/getpdo-usage

I would never do such a query in eloquent or query Builder like above.

the second I have to use the word Raw, I do a regular query.

Will boot up laptop shortly and give another example from cronix.

Here's another good example: (cronix provided)

https://laracasts.com/discuss/channels/laravel/sql-native-to-query-builder

quote

$bindings = [
    'product_type_id' => 1,
    'service_sub_type_id' => 2,
    'school_id' => 57,
    'status_id1' => 2,
    'status_id2' => 3
];

$users = DB::select('SELECT DISTINCT CONCAT(u.last_name, ", ", u.first_name ) AS full_name, ci.created_at AS date_purchase
FROM cart_items AS ci
LEFT JOIN products AS p ON ci.product_id = p.id
LEFT JOIN carts AS c ON ci.cart_id = c.id
LEFT JOIN `status` AS s ON ci.status_id = s.id

INNER JOIN users AS u ON c.user_id = u.id
INNER JOIN school_users AS su ON u.id = su.user_id

INNER JOIN
    (
    SELECT MAX(created_at) AS created_at1, cart_id
    FROM cart_items
    GROUP BY `cart_id`
    )p2 ON ci.cart_id = p2.cart_id AND ci.created_at = p2.created_at1

WHERE p.product_type_id = :product_type_id AND p.service_sub_type_id = :service_sub_type_id AND su.school_id = :school_id AND ci.status_id = :status_id1 OR ci.status_id = :status_id2
ORDER BY ci.created_at DESC', $bindings);

unquote

Note however db facade returns also array of objects, but getPdo() you are in full control, it's the PDO instance directly. so you can:

$quy = $sth->fetchAll(\PDO::FETCH_ASSOC);
$quy = $sth->fetch(\PDO::FETCH_ASSOC);  // just one

//or

$quy = $sth->fetchAll(\PDO::FETCH_OBJ);
vincej's avatar
Level 15

ok, thanks regular query with subquery it will be.

Cronix's avatar
Cronix
Best Answer
Level 67

@vincej using your original data from the first post

foreach ($allocation as $object) {
    // does this inv_product_id exist as an array key in $orders?
    if (isset($orders[$object->inv_product_id])) {
        // yes, add allocated to $orders at same key
        $orders[$object->inv_product_id] += $object->allocated;
    }
}
dump ($orders);
array:2 [▼
  123 => 135 // new total for id 123
  789 => 20  // new total for id 789
]

Not sure if this is exactly what you were looking for (I didn't read everything in this thread), but wanted to show you that it's not an issue to iterate an array of objects. You just have to use object notation on the object! I tried to label everything to make it clear what was going on.

It's just iterating the array of allocations, checking to see if that allocations' inv_product_id exists as an array key in your $orders array. If it does, add the value of the allocation to that array to create a new total for it in the $orders array.

1 like
vincej's avatar
Level 15

Wow ! That is amazing! Thank you very much. I have to admit that I do not thoroughly understand what is happening here. I have not seen this kind of expression before, where you both sum allocated and inv_product_id, then simultaneously create a new array with just the use of +=

Thank you !

Cronix's avatar

@VINCEJ - I didn't create a new array. I added the new value to the $orders array (sum of original value of that element in the array with the new allocated value). So $orders is the same array as the original, but just has the new sum.

$a += $b is shorthand $a = $a + $b.

$a = 2;
$b = 5;

$a = $a + $b; // $a is now 7
// same as
$a += $b; // $a = 7

http://php.net/manual/en/language.operators.assignment.php

jlrdw's avatar

@cronix Why does toArray() work with eloquent but not query Builder. I had never noticed that before until this question.

@vincej see I told you he would know how to do that.

Cronix's avatar

Not sure. I almost never use toArray() so never really noticed. I just use object notation on objects. It's inefficient to convert it unless you really need to.

vincej's avatar
Level 15

@harendrasingh Thank you. So I Googled "array of allocations" and did not find anything which explained things. What am I missing??

vincej's avatar
Level 15

@cronix Thanks for the explanation. Man I was banging my head against a brick wall with Array_push.

I am very familiar with the += syntax. However, what surprised me is that using this approach, you did not need to create a new array. You did not need to stipulate what would be the keys, nor the values. What also surprised me is that += creates a whole new set of values in the $object array at all. I mean, the preceding values are not overwritten by the last value. I have never used += in this form to achieve this result.

jlrdw's avatar

@VINCEJ - I discovered something, remember how with eloquent this works:

$dogs = Dog::where('adopted', '=', 0)->get()->toArray();

Neither of us could not get it to work in query builder.

But Found a stackoverflow flow answer,

$dogs = DB::table('dc_dogs')->where('adopted', '=', 0)->get();
$dogarray = json_decode(json_encode($dogs), True);

Works as a work a round, shared with you just incase you ever need that.

Mean while I am going to put an issue in and see what happens, to me ->toArray() should work with query builder as well.

But glad you got all figured out.

I put in Issue #27722 https://github.com/laravel/framework/issues/27722

vincej's avatar
Level 15

@jlrdw Thanks for that. I actually saw that on SO, however, it produced an array of arrays. For me this still created the challenge of of figuring out how to get rid of the key => value, inv_product_id =123 and allocated = 4 when I needed the resulting array to be 123 => 4

Anyway, as you predicted @cronix came to the rescue with a beautifully elegant solution. Which I understand now.

If it wasn't for people like you and @cronix and @snapey I would given up years ago. Cheers !

vincej's avatar
Level 15

@cronix I'm having a little problem with that foreach you gave me last week. I have played with this a hundred times which way, I have no idea why it is doing what it is doing. Can you tell me why the foreach is jumping back to the $orders array and looping over it a second time? The result is that it is saving the values into the DB twice. Only after the second loop through does it hit the redirect. Here is the full set of code so hopefully there is little guess work:

    $orders = [];
        $orders = array_combine($id,$qty);
        
        foreach ($get_allocation as $object) {
             if ((!empty($orders[$object->inv_product_id]) )) {
             $orders[$object->inv_product_id] += $object->allocated;
            }
        }

        //This updates the DB with the new order
        foreach($orders as $key=>$value){
            DB::table('inventory')->where('inv_product_id', '=',$key)->update(['allocated' => $value]);
        }


        return redirect('open_quotes');

The Contents of $Orders looks like this:

$orders = {array} [2]
 123 = "2"
  = null

$get_allocation looks like this:

$get_allocation = {array} [1]
 0 = {stdClass} [2]
  inv_product_id = "123"
  allocated = "2"

Many Thanks !!!! :o)

Cronix's avatar

Is that what $orders is before you manipulate it, or after?

What is the output of

$orders = array_combine($id,$qty);
dd($orders);

?

I really don't think it contains the data you think it does, and most likely isn't like the array you originally showed, which was

$orders = {array} [6]
 123 = "131"
 789 = "12"

I think you're mangling it with your array_combine().

Next

Please or to participate in this conversation.