Jump to content
Larry Ullman's Book Forums

Recommended Posts

Hi all,

I have a multidimensional array in which one of the elements is a number. I want to be able to add these numbers togethor to get a grand total for this element from all the arrays within the multidimensional one. I've tried the following line of code:

 

echo'
<p>Total:' . array_sum($_SESSION['curtain_basket']['final_curtain_quote']) . '</p><br />';

 

I get the following error:

 

 

An error has occurred in script 'C:\xampp\htdocs\Dis Soft Furnishings\web\basket.php' on line 55: Undefined index: final_curtain_quote

Date/Time: 4-24-2012 16:00:04

. print_r(Array, 1) .

 

 

An error has occurred in script 'C:\xampp\htdocs\Dis Soft Furnishings\web\basket.php' on line 55: array_sum() expects parameter 1 to be array, null given

Date/Time: 4-24-2012 16:00:04

. print_r(Array, 1) .

 

I ran a print_r function for $_SESSION['curtain_basket'] so I know that element is there. Could it be that it's become a string somewhere along the line as opposed to a number? Does array_sum only add the entire contents of an array?

 

Cheers

Paul

Link to comment
Share on other sites

You need to read the function description. You are getting the error message because $_SESSION['curtain_basket']['final_curtain_quote'] is not an array. (And the function needs an array).

 

array_sum() calculates the total of all numeric values in an array. That means:

 

$array = array(2, 5, 3, 10, "strings will be skipped");
$sum = array_sum($array); // $sum is now 20

 

I bet this is really not what you are looking for. This is probably more like what you want:

$sum = 0;
foreach ( $_SESSION['curtain_basket'] as $value )
{
  // Will add $value if it's numeric, else 0 (no change)
  $sum += (int) ( is_numeric($value) == true ) ? $value : 0;
}

 

You might need to change the foreach conditional a bit. I don't know exactly how the $_SESSION array looks.

  • Upvote 1
Link to comment
Share on other sites

Antonio, I remember Paul bringing up this array the other day, and my feeling was that it's a multidimensional array where the top-level array is an associative array (which contains keys like 'curtain_basket'), and each of those keys contains another associative array for its value. In other words, I *think* your solution will only add up the value in one of the subarrays in the multidimensional array, but I could be wrong, so I apologize if that's the case.

 

Anyway, Paul seems to want to use the array_sum function, so he should probably do something like the following:

 

$total = 0;

foreach ($SESSION as $key => $value) {

 total += array_sum($SESSION[$key]);

}

echo '<p>Total: ' . $total . '</p><br />';

 

Anyway, I guess we'll have to wait for Paul to respond to see what's up. Not too sure myself (and sorry if I stepped on your toes there, Antonio).

Link to comment
Share on other sites

Gents,

To summarise. I have a MD array that is a session. The top level is a basket which is an indexed array of quotes. Each quote is an assoc. array. The user can add quotes to their basket. It would have been far esaier to have used a DB but I don't know who the user is until they checkout. One of the keys (is that the right word?) of each quote array is a price. It is this price that I'm trying to total on the basket page by accessing that part of each quote array.

 

I did actaully try Antonio's approach using a foreach function on $_SESSION['curtain_basket']['final_curtain_quote'] and then the '+=' but I think I was getting my syntax wrong because it didn't work, as per below. I came to the conclusion that there must be an easier way to do this so looked at the PHP Manual and tried array_sum. I looked at it again this morning and am still not clear on what can and can't be 'summed' with an array_sum function. For instance HartleySan is using array_sum($_SESSION[$key]). Anyway I tried the following:

 

$total = 0;
foreach ($_SESSION['curtain_basket']['final_curtain_quote'] as $value) {
 $total += $value;
}
echo '<p>Total: ' . $total . '</p><br />';

 

Now I think that the above is failing because $_SESSION['curtain_basket'] does not have a key called 'final_curtain_quote', its keys are 0,1,2 etc. If I wanted to access the 'final_curtain_quote' information I would need to access:

$_SESSION['curtain_basket'][0]['final_curtain_quote']

$_SESSION['curtain_basket'][1]['final_curtain_quote']

$_SESSION['curtain_basket'][2]['final_curtain_quote'], etc.

 

Is that right? But how to do that in a foreach loop? If I could do that then I can use '+=' as per both your suggestions.

Cheers

Paul

 

PS. I do very much appreciate all the help I receive in this forum, especially you guys and Larry and if we weren't spread around the world I'd buy you a beer (or 2)! If it's any conciliation for the seemingly endless stream of questions I do spend quite some time trying to work it out myself before resorting to this forum. I also don't just want to know the answer of how to do something but try to understand why it's working. Anyway, if I don't come accross as appreciative as I should, I'm sorry.

Link to comment
Share on other sites

Paul, you don't need to apologize for all your questions. We all just pay-it-forward here, so it's cool. A few years back, I used to annoy the crap outta Larry with my constant questions. I still sometimes laugh when I think about it. Also, we can tell that you're working hard, so we're more than happy to help.

 

To answer your question, both Antonio's method and my method will work fine, assuming your array is structured the right way. However, given your previous post, the array structure is different from what I imagined. From what I can tell, you have a 3D array, but the weird thing is, the top-level array seems to only have one element with the key 'curtain_basket'. Is that indeed the case? If you're storing other information in the array, then I can understand the need for the key for the top-level array, but otherwise, I'd get rid of the top level.

 

If you decide to keep the top array, then changing the $SESSION part in the code I provided to $SESSION['curtain_basket'] should make things work properly.

Lemme know what happens.

 

Thanks.

Link to comment
Share on other sites

Hiya,

A 3D array...blimey! The reason I have $_SESSION['curtain_basket'] is that once I get this lot to work I need to do the same thing for Roman Blinds, i.e. $_SESSION['roman_blinds'] . So I could have a user that has multiple curtain and Roman Blind quotes in their basket.

 

I tried your suggestion as follows:

  $total = 0;
  foreach ($SESSION['curtain_basket'] as $key => $value)
  {
  $total += array_sum($SESSION[$key]);
  }

  echo '<p>Total: ' . $total . '</p><br />'
;

 

I got the following errors:

 

 

An error has occurred in script 'C:\xampp\htdocs\Dis Soft Furnishings\web\basket.php' on line 80: Undefined variable: SESSION

Date/Time: 4-25-2012 13:08:11

. print_r(Array, 1) .

 

An error has occurred in script 'C:\xampp\htdocs\Dis Soft Furnishings\web\basket.php' on line 80: Invalid argument supplied for foreach()

Date/Time: 4-25-2012 13:08:11

. print_r(Array, 1) .

 

Total: 0

 

From your code above would it not be trying to add up 0, 1, 2 etc depending on the number of quotes in the basket. Just trying to understand how it would know to add up 'final_curtain_quote' within each quote, which is only one of many elements. Is there a way of using foreach loops nested within foreach loops to reach 'inside' and then use the '+=' bit to add them togethor? The idea is there, the syntax is beyond me. Something like:

 

foreach ($SESSION['curtain_basket'] as $value)
  {
		    foreach ($value as $sum)
		    {
		    $total += array_sum($sum['final_curtain_quote']);
		    }
  }  
  echo '<p>Total: ' . $total . '</p><br />';

 

Cheers

Paul

Link to comment
Share on other sites

I agree with Jon. It seems like we maybe should take a look at your session array. It feels wrong to me.

 

I would start with your naming. Why 'curtain_basket' instead of 'basket'? Why 'final_curtain_quote' instead of 'quote'? I don't say this to criticize you, because I think you went for clarity when choosing these names. My guess are that they get to long and complicated. Keep it simple.

 

Started to look at your "A $_Session Multidimensional Array" post again. I think we need to identify the products in this setup. track poles are the "hangers" for the curtains, right? Do they differ in price? Are they stored in the db? fabric_drop and fabric_width describe the curtains height and width, right? How do you price that? I don't know the other stuff you wrote about in that thread, but selection them is adding to the price, yes? Can you choose different lining and are there price differences?

 

I think I'm starting to make my point now. The question is what you can identify as "products" here. I think we need to build arrays of arrays here. Most of what you save her has price, right? And names, ids in the DB, and so on. To keep track of what they want, you need to build several small products (poles, lining, stuffing, etc) that together combine the curtain. I'm starting to think the session array should look more like this:

 

$_SESSION['curtain'] = array(
// Store what kind of fabric, sizes, and price for this material
  "fabric" => array(
	"id" => 10,
	"type" => "Chinese silk",
	"width" => 75,
	"height" => 175,
	"price" => 10, // You know better how to calculate this
),

// Poles cost too. If they want to upgrade pole, it costs
"pole" => array(
	"id" => 54,
	"name" => "Curtain master 3000!",
	"size" => 100,
	"price" => 2,
),

// Customer want heading. Price is set
"heading" => array(
	true,
	"price" => 1
),

// Don't want this, and cost is set to 0
"lining"  => array(
	false,
	"lining_type" => "Elegant",
	"price" => 0
),	

// Dunno what this is...
"fullness" => array(
	"price" => 2,
	"fullness" => "Extra Fluffy",
),
// or this...
"interlined" => array(
	"Price" => 3
),
"total_price" => 0, // Add amount for each product here for the total
"total_products" = 0,
);

 

With this kind of code, you can easily summarize the price and send you a good description of that the customer wants. You should create several functions that can create these small products before the curtain is complete and ready to order: Something along this: (Notice the example above was filled out. Here comes how you can use it:)

 


// User browses fabric types and find a fabric she wants.
// The id and fabric price is found in a DB / or already stored in the product (maybe via get or something)
// When the user spesifies the needed data, the total cost is calculated for the product.
// The product is then added as one part of the full curtain product.

   fabric_pick( 42, "Cotton Candy patterned curtains", 75, 180, 1 );

// Same pattern as above for all products
   pole_pick();
   heading_pick(bla, bla, bla);
   lining_pick( true, "Strong lining", 4 );

// Finally, all products are choosen:
if ( $_SESSION['curtain']['total_products'] == 6 ) // We have 6 products
{
	// Now the curtain is complete. It can be bought, sent to production team/whater
   }

// User picks fabric. Add product to session
function pick_fabric( $fabric_id, $fabric_name, $width, $height, $some_price_per_cm_meter_whatever )
{
	$fabric_price = ($width * $height) * $some_price_per_cm_or_meter_whatever;

	// Add the fabric product values
	$_SESSION['curtain']['fabric'] = array(
		"id" => $fabric_id,
		"name" => $fabric_name,
		"width" => $width,
		"height" => $height,
		"price" => $fabric_price,
	);

	// Update number of products for THIS curtain.
	// We want to keep track of fabric, poles, headings, etc
	// to know when the CURTAIN is done customizing an ready to be ordered.
	$_SESSION['curtain']['total_products']++;

	// And update total price
	$_SESSION['curtain']['total_price'] += $fabric_price;
}

// User picks a pole. Add product to session
function pole_pick( $value, $value... $value )
{
	// Add the pole product values
	$_SESSION['curtain']['pole'] = array(
		"label" => $value,
		.....
		"label" => $value
		.....
	);

	// And remember that we now added a pole product.
	$_SESSION['curtain']['total_products']++;

	// And update total price
	$_SESSION['curtain']['total_price'] += $calculated_pole_price;
}

 

Not too sure myself (and sorry if I stepped on your toes there, Antonio).

 

No worries. I'm very hard to offend. You won't be able to do that just by discussing programming. ;)

  • Upvote 1
Link to comment
Share on other sites

Thanks for the reassurance, Antonio. Was legitimately a bit worried.

 

Also, Paul, you probably got an error because you didn't change the reference to $_SESSION in the foreach loop body to $_SESSION['curtain_basket'].

If you change that one too, it should work.

 

With all that said, I ultimately agree with Antonio that you'd be best to take a step back and first restructure your array based on exactly what you want to accomplish, and only after that's done, worry about how to add up the arrays.

Link to comment
Share on other sites

Hehe. Nah. I mess up when it becomes to many nested arrays. I'm more of a fan of adding objects to arrays and play with them that way instead. I hate doing array operations on multidimensional arrays as they ca be both tricky and little efficient. (That was generally speaking. The object solution probably has a lot more overhead than mapped key, value pairs for this kind of small data structures)

 

If I were to program this myself, I would built a normal array with "key" => $object, pairs. Then I would send that array to the session array.

 


$curtain_array( "fabric", new Fabric( input ), "pole", new Pole(input));

$_SESSION['product'][] = $curtain_array;

foreach ( $_SEASSION['product']['the_curtain_id_received'] as $obj ) {
  $this->price += $obj->getPrice();
}

 

Implementing some simple interface will pretty much do the job here. A base class could get a lot of the job done and prevent code duplication == saved time. But I gotta say, I learned OOP in Java, not in PHP. I know this is not usually "how you do it", just my preferred way.

Link to comment
Share on other sites

Guys,

Antonio, wow. That post must have taken you ages. I read it and then stepped away from the computer, made myself a coffee and had a think about the points you were making. I have no idea how objects work. I think that Larrys PHP5 advanced book starts on those which I have just began. I think I need to divide my time up between trying to make this project work and learning more.

 

A little bit more background may help here. A curtain quote is 99% labour. There are nearly no products, except for fabric that the user supplies. The pole refers to the width of the window, which the user supplies (usually already attached to their wall!). Most of the information collected from the form, and therefore the contents of the quote arrays are in order to supply the parameters for making them. There is no fixed stock to choose. It is very different from say, ordering a car, where you choose additions to the main car that can be stored in a database. The closest analogy I can think of is of supplying a website. Primarily the supply of a website is only labour cost, there is no stock. However there are loads of parameters that affect that quote.

 

HartleySan. I tried as you suggested:

$total = 0;
  foreach ($SESSION['curtain_basket'] as $key => $value)
  {
  $total += array_sum($SESSION['curtain_basket']);
  }

  echo '<p>Total: ' . $total . '</p><br />';

 

There was the same error message.

 

Is there a way of accessing each final quote array element, assigning them a different variable, like $final_quote0, $final_quote1, $final_quote2 and then adding them togethor. It would mean that the array_sum function would not be needed? Just trying to think outside the box a bit.

 

The irony here is that this is the last bit of the basket page. I've just finished the process whereby a user can remove individual quotes from their basket and it worked fine. What I'm thinking as a last resort is that I could not supply a total on the basket page. The next step is that the user either goes somewhere else, the basket is not saved and the session is removed or they 'checkout' in which case they will be asked to register and then the quotes can go onto a Db and I can total them up from there. Not perfect but needs must.......

 

This is good stuff.

Cheers

Paul

Link to comment
Share on other sites

That's because I'm retarded, Paul. Sorry for the mistake on my part. It probably would have been best for me to recreate your $_SESSION array and then test it myself.

After thinking about it more, I think you need to make the following change:

 

Old:

$total += array_sum($SESSION['curtain_basket']);

 

New:

$total += array_sum($SESSION['curtain_basket'][$key]);

 

Try that, please, and sorry for the runaround.

If that doesn't work, well then, I might just create your $_SESSION array and test things out until it works.

Link to comment
Share on other sites

Now I think that the above is failing because $_SESSION['curtain_basket'] does not have a key called 'final_curtain_quote', its keys are 0,1,2 etc. If I wanted to access the 'final_curtain_quote' information I would need to access:

$_SESSION['curtain_basket'][0]['final_curtain_quote']

$_SESSION['curtain_basket'][1]['final_curtain_quote']

$_SESSION['curtain_basket'][2]['final_curtain_quote'], etc.

 

That's why I said the array seemed strange. It's just a nasty array. :)

 

// Get array size
$size = count($_SESSION['curtain_basket']);

// Keep count
$num = 0;

// loop that shit
for ( $i=0; $i < $size; $i++ ) {
$num += (int) $_SESSION['curtain_basket'][$i]['final_curtain_quote'];
}

 

Paul: Never mind about the objects yet. They are not so hard to get, but you won't need them yet is what I take for your explanation. Tell me how that code works.

Link to comment
Share on other sites

Gents,

Sorry for the delay in responding, had a couple of days off.

 

Paul Swanson, that was great. I changed the code as you suggested and added the $key bit that HartleySan suggested and it worked. Well, actually it worked too well! It added the entire curtain_basket array togethor, the drop numbers, the width etc. which made it a very expensive quote! I played with it a bit more to try and isolate just the totals but couldn't get it to work.

 

I then tried Antonio's suggestion and bingo! I added a touch of number formatting and it works a treat. By way of a little but more information, as I mentioned above I used the unset function to allow users to remove individual array elements (quotes) from the quote array. Antonio's suggestion came up with an error because using the unset function doesn't reset the keys, so the incremental loop failed. So I used the array_values function to reset the keys and Antonio's answer worked a treat.

 

You have no idea how much I have learned from this epic and really appreciate all the help from everyone.

 

Cheers

Paul

Link to comment
Share on other sites

 Share

×
×
  • Create New...