# Bit of coding help? (PHP)

**URL:** https://boards.straightdope.com/t/bit-of-coding-help-php/544972
**Category:** In My Humble Opinion
**Created:** [June 29, 2010, 7:45pm UTC](https://boards.straightdope.com/t/bit-of-coding-help-php/544972 "2010-06-29T19:45:43Z")
**Posts on this page:** 9
**Page:** 1

<div class="post-metadata">

### Author: ![jjimm](https://avatars.discourse-cdn.com/v4/letter/j/ba8739/32.png) [@jjimm](https://boards.straightdope.com/u/jjimm)
#### Post date: [June 29, 2010, 7:45pm UTC](https://boards.straightdope.com/t/bit-of-coding-help-php/544972/1 "2010-06-29T19:45:43Z")

</div>

I’m not a programmer but in the past I have tinkered with other people’s code to reasonable effect.

As part of a freelance job, I’ve inherited a very simple PHP-based shopping cart, with no SQL buddy present. I’m clueless about SQL so this wouldn’t be an option.

Stock data is contained in a tab-delimited text file that contains stuff like product name, stock id, price, postage, etc. The shop PHP deconstructs this when the page loads, and assigns session array/variable names to each part of the stock table. The cart file then uses session variables to add/remove products, and the checkout part sends a bunch of totalled variables to PayPal.

The client is asking me to make a change to this: where currently each product bears a postage price, and it all gets totalled up and sent to PayPal, what he wants is that each product bears a _weight_, and the script totals up all product weights, then refers to a table of weight thresholds to calculate the total postage value.

E.g.

0 - 50g =\> £1  
51g - 100g =\> £2.50  
101g - 250g =\> £5  
250g - 500g =\> £10  
500g + =\> £15

So, I can conceptually work out what to do, and will be able to get about 80% of the way there, but know of no elegant way to create a lookup of the above table (which will necessarily be a txt file or embedded into the PHP) without using dozens of nested IF statements. Is there some kind of thing that checks a number and compares it with numbers in an array, then establishes if it’s larger than one part of array and smaller than the other part?

Thanks!

---

<div class="post-metadata">

### Author: ![umop\_ap\_sdn](https://avatars.discourse-cdn.com/v4/letter/u/dbc845/32.png) [@umop\_ap\_sdn](https://boards.straightdope.com/u/umop_ap_sdn)
#### Post date: [June 29, 2010, 8:15pm UTC](https://boards.straightdope.com/t/bit-of-coding-help-php/544972/2 "2010-06-29T20:15:17Z")

</div>

Iterate through the array until you get to the first element whose value is larger than your variable?

---

<div class="post-metadata">

### Author: ![UncleRojelio](https://sea3.discourse-cdn.com/straightdope/user_avatar/boards.straightdope.com/unclerojelio/32/3160_2.png) [@UncleRojelio](https://boards.straightdope.com/u/UncleRojelio)
#### Post date: [June 29, 2010, 8:29pm UTC](https://boards.straightdope.com/t/bit-of-coding-help-php/544972/3 "2010-06-29T20:29:55Z")

</div>

If there were a thousand such decisions to make I’d say ‘divide and conquer’, maybe with a binary tree. In this case, just go with the ‘if’ statements.

---

<div class="post-metadata">

### Author: ![jjimm](https://avatars.discourse-cdn.com/v4/letter/j/ba8739/32.png) [@jjimm](https://boards.straightdope.com/u/jjimm)
#### Post date: [June 29, 2010, 8:52pm UTC](https://boards.straightdope.com/t/bit-of-coding-help-php/544972/4 "2010-06-29T20:52:03Z")

</div>

> [@umop\_ap\_sdn](#):
>
> Iterate through the array until you get to the first element whose value is larger than your variable?

Damn, I’ve just noticed another instruction from the client whereby over 4kg, each additional 2kg gets another cash value added to the total.

I can express it logically but sure as hell can’t turn that into code.

Think I’m going to have to give up on this. ☹

---

<div class="post-metadata">

### Author: ![Racer1](https://avatars.discourse-cdn.com/v4/letter/r/ee59a6/32.png) [@Racer1](https://boards.straightdope.com/u/Racer1)
#### Post date: [June 29, 2010, 9:13pm UTC](https://boards.straightdope.com/t/bit-of-coding-help-php/544972/5 "2010-06-29T21:13:50Z")

</div>

Could you bodge something clever with a switch statement?

[http://php.net/manual/en/control-structures.switch.php](http://php.net/manual/en/control-structures.switch.php)

Scroll down for more info on how people are using the statement in clever ways.

---

<div class="post-metadata">

### Author: ![jjimm](https://avatars.discourse-cdn.com/v4/letter/j/ba8739/32.png) [@jjimm](https://boards.straightdope.com/u/jjimm)
#### Post date: [June 29, 2010, 9:15pm UTC](https://boards.straightdope.com/t/bit-of-coding-help-php/544972/6 "2010-06-29T21:15:23Z")

</div>

Here’s the logic:

Price = 1 (minimum price)

weight\_array(101,251,501,1001,2001)  
price\_array(1.5,2.5,4,5,6)

IF (weight \> 4000)  
Price = 8 + round down((weight - 4000) / 2000)\*2  
ELSE  
FOR [integer++,weight\_array\_length]  
IF weight\_array[integer] \> weight  
Price = price\_array[integer] END LOOP  
NEXT

Any idea how to turn that into code?!

---

<div class="post-metadata">

### Author: ![Mtgman](https://avatars.discourse-cdn.com/v4/letter/m/b5a626/32.png) [@Mtgman](https://boards.straightdope.com/u/Mtgman)
#### Post date: [June 29, 2010, 11:29pm UTC](https://boards.straightdope.com/t/bit-of-coding-help-php/544972/7 "2010-06-29T23:29:38Z")

</div>

Does PHP allow hashes? I think it’s an offshoot of Perl, and if I had to do this all self-contained in Perl I’d probably do a hash of hashes where the outer key is a pre-defined postal amount, and the inner hash is an upper bound and lower bound for that range. So you could iterate a loop through your keys, sorted ascending, and then do one comparison per loop to see if it was within the range for that postal amount. If you run through the loop and you don’t have a winner, then it’s over the maximum and you apply the last value(highest) plus the extra.

[This is a site I found which looks like it knows what it’s talking about](http://pleac.sourceforge.net/pleac_php/hashes.html). Read the intro first. Check out the section on “hashes with multiple values per key” for an example closer to what I had in mind.  
Enjoy,  
Steven

---

<div class="post-metadata">

### Author: ![Sofis](https://avatars.discourse-cdn.com/v4/letter/s/e5b9ba/32.png) [@Sofis](https://boards.straightdope.com/u/Sofis)
#### Post date: [July 2, 2010, 7:45pm UTC](https://boards.straightdope.com/t/bit-of-coding-help-php/544972/8 "2010-07-02T19:45:48Z")

</div>

> [@jjimm](#):
>
> Here’s the logic:
> 
> Price = 1 (minimum price)
> 
> weight\_array(101,251,501,1001,2001)  
> price\_array(1.5,2.5,4,5,6)
> 
> IF (weight \> 4000)  
> Price = 8 + round down((weight - 4000) / 2000)\*2  
> ELSE  
> FOR [integer++,weight\_array\_length]  
> IF weight\_array[integer] \> weight  
> Price = price\_array[integer] END LOOP  
> NEXT
> 
> Any idea how to turn that into code?!

According to the php tutorials I just looked up, this should be a correct translation of your logic:

```auto

$price = 1; // minimum price

$weights = array(101,251,501,1001,2001);
$prices = array(1.5,2.5,4,5,6);

if (weight > 4000)
{
  $price = 8 + ((weight - 4000) / 2000)*2;
}
else
{
  for ($i = 0; $i < 5; $i++)
  {
    if (weights[$i] > weight)
    {
      $price = $prices[$i];
      break;
    }
  }
}

```

However, your logic is not correct. If something has a weight above 2000 but less than 4000, the price will remain as the minimum.

---

<div class="post-metadata">

### Author: ![jjimm](https://avatars.discourse-cdn.com/v4/letter/j/ba8739/32.png) [@jjimm](https://boards.straightdope.com/u/jjimm)
#### Post date: [July 3, 2010, 11:38am UTC](https://boards.straightdope.com/t/bit-of-coding-help-php/544972/9 "2010-07-03T11:38:00Z")

</div>

Thanks all, especially **Sofis**. I cracked it myself, and have tested the following at all weights - it works, even for for weights greater than 2kg up to 4kg.

```auto

// $weight already established

$postage = 0;
$weight_ceiling = 4;
$postage_ceiling = 8.22;
$postage_above_ceiling = 2.8;
$postage_threshold = array(0.1, 0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2, 4);
$postage_threshold_price = array(1.39, 1.72, 2.24, 2.75, 3.35, 4.50, 5.20, 5.90, 6.60, 8.22);
$postage_threshold_length = sizeof($postage_threshold);

if ($total_weight >= ($weight_ceiling))
	{
	$remainder = ($total_weight-$weight_ceiling);
	$weight_above_ceiling = ceil($remainder/2);
	$total_postage = $postage_ceiling+$weight_above_ceiling*$postage_above_ceiling;
	}
else
	{
	for ($i = 0 ; $i < $postage_threshold_length ; $i++)
		{
		if ($total_weight <= $postage_threshold[$i])
			{
			$total_postage = $postage_threshold_price[$i];
			break;
			}
		}
	}

```
