views:

49

answers:

4

On a website I have a number of small PHP scripts to automate changes to the text of the site, depending on a figure that's calculated from a MySQL database. The site is for a fundraising group, and the text in question on the home page gives the total amount raised.

The amount raised is pulled from the database and rounded to the nearest thousand. This is the PHP I use to round the figure and find the last three digits of the total:

$query4 = mysql_query("SELECT SUM(amountraised) AS full_total FROM fundraisingtotal;");
$result4 = mysql_fetch_array($query4);
$fulltotal = $result4["full_total"];
$num = $fulltotal + 30000;
$ftotalr = round($num,-3);
$roundnum = round($num);
$string = $roundnum;
$length = strlen($string);
$characters = 3;
$start = $length - $characters;
$string = substr($string , $start ,$characters);
$figure = $string;

(£30,000 is the amount that had been raised by the previous fundraising team from when the project first started, which is why I've added 30000 to $fulltotal for the $num variable)

Currently the text reads:
the bookstall and other fundraising events have raised more than &pound;<? echo number_format($ftotalr); ?>

I've just realised though that because the PHP is rounding to the nearest thousand, if the total's for example £39,200 and it's rounded to £40,000, to say it's more than £40,000 is incorrect, and in that case I'd need it to say 'almost £40,000' or something similar. I obviously need to replace the 'more than' with a variable.

Obviously I need to test whether the last three digits of the total are nearer to 0 or 1000, so that if the total was for example £39,2000, the text would read 'just over', if it was between £39,250 and £39,400 something like 'over', between £39,400 and £39,700 something like 'well over', and between £39,700 and £39,999, 'almost.'

I've managed to get the last three digits of the total as a variable, and I think I need some sort of an if/else/elseif code block (not sure if that would be the right approach, or whether to use case/break), and obviously I'm going to have to check whether the figure meets each of the criteria, but I can't figure out how to do that. Could anyone suggest what would be the best way to do this please?

A: 

You might not need to change the text... take a look at the floor function http://php.net/manual/en/function.floor.php

It will always round down, so you can still say 'more than'.

Lizard
I did look at the floor function when I first started setting it up, but the problem is that if it's constantly rounding down, it doesn't show the total rising, which particularly at the beginning of each fundraising year is going to be a problem, because until the first 1000 was raised each year the total wouldn't rise, which is a problem for people checking back to see how it's going because it doesn't look as though it's getting anywhere! ;-)
NeonBlue Bliss
+1  A: 

Instead of nested if else blocks, you could have a function that takes in the dollar amount and inside the function throw the variable in a switch case statement and at a particular case return the correct echo'd text.

Switch cases provide readability over several if else statements. If you need coIde examples, let me know.

Update:

Performing comparisons on integers only, switch case is the best bet. When comparing conditions that result in a boolean value, using if else is what you need.

I had took your code and switched the case to be if else and here is what it looks like with an example output:

function qualifier($figure) {
        if ($figure < 249) return "just over";
        elseif ($figure < 399) return "over";
        elseif ($figure < 699) return "well over";
        elseif ($figure < 999) return "almost"; 
        else return "No number entered";
     }

echo "We are " . qualifier(250) . " our goal!";
// outputs: "We are over our goal!"
Anthony Forloney
I'm obviously doing something wrong here. This is what I've tried: function qualifier($figure) { switch ($figure) { case ($figure < 249): echo "just over"; break; case ($figure < 399): echo "over"; break; case ($figure < 699): echo "well over"; break; case ($figure < 999): echo "almost"; break; default: echo "No number entered"; } } ..and I'm getting a 'Call to undefined function qualifier()' error. (I'm not entirely sure I've set the comparisons up properly either!)
NeonBlue Bliss
How are you calling the function?
Anthony Forloney
<? echo qualifier($figure); ?>
NeonBlue Bliss
I'm on my phone at the moment, otherwise I'd throw the code into Eclipse to test it out. I think switch cases work on integers only, try to change the code to add integers only as your case and see if it works. If so, then having comparisons causes a problem.
Anthony Forloney
Also, if that truly is the cause of the problem, id switch the switch case for `if else` statements and leave the logic the same.
Anthony Forloney
Thanks Anthony - you're a star! That's working perfectly now!
NeonBlue Bliss
Not a problem, I am glad I could help. Good luck!
Anthony Forloney
A: 

I would use "approximately" to cover all cases!

Smandoli
+1  A: 

The simplest and most elegant solution imho would be, like Lizard pointed out, to floor the value and always say "over". You could even make exception for the first-1000 problem and floor anything below that to the next 100 or so, something like...

<?
function getFlooredText($amount) {
    if($amount < 1000) {
        return floor($amount/100)*100;
    } else {
        return floor($amount/1000)*1000;
    }
}

echo "We've raised over &pound;" . getFlooredText(455) . "\n"; // 400
echo "We've raised over &pound;" . getFlooredText(1455) . "\n"; // 1000
echo "We've raised over &pound;" . getFlooredText(38800) . "\n"; // 38000
?>

If you absolutely don't want that you could always do a four or five layer if-sandwich, it would be the easiest approach towards the idea you described but maybe not the prettiest. Something like this, if I understood where you were going with it...

<?
function getRoundedText($amount) {
    $n = substr($amount, -3);
    if($n < 250) {
        return "just over &pound;" . round($amount, -3);
    } elseif($n < 500) {
        return "well over &pound;" . round($amount, -3);
    } elseif($n < 750) {
        return "close to &pound;" . round($amount, -3);
    } elseif($n < 1000) {
        return "almost &pound;" . round($amount, -3);
    }
}

echo "We've raised " . getRoundedText(38200) . "\n";
echo "We've raised " . getRoundedText(38400) . "\n";
echo "We've raised " . getRoundedText(38700) . "\n";
echo "We've raised " . getRoundedText(38900) . "\n";
?>

Hope that helps.

Gussi
I don't know why, but using the second function I'm getting a 'Call to undefined function getroundedtext()' error.
NeonBlue Bliss
Make sure you got the function definition in your code, or if you've changed its name be sure to call it by that name.
Gussi
Thanks Gussi. I double-checked (and triple checked!) the names again (I've tried so many variations on the code it all got rather confusing) but everything seems to be in order. Having played about with the code below though and finally got that working, I'm thinking it might have been a couple of commented lines that were in the middle of a load of code because as soon as I took those two out and moved the code slightly further up the page it worked okay. Thanks anyway.
NeonBlue Bliss