Bit of coding help? (PHP)

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!

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

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.

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. :frowning:

Could you bodge something clever with a switch statement?

http://php.net/manual/en/control-structures.switch.php

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

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?!

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. 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

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



$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.

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.


// $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;
			}
		}
	}