PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!
Hello all...I'm relatively new to PHP but not to programming. I'm running into a weird issue. I'm writing a type of accounting web site for my work. It keeps track of payments made by each employee for a staple fund. Payment is due every two weeks and I have a MySQL db that keeps the date a person paid, amount paid, how much their next payment should be and the date that payment is due. All relatively simple.
I have a screen where I ask for what pay period a user wants to view and then the PHP code determines each persons balance up to that pay period. I got it to work, but as I try to run it multiple times, the $num_payperiods ends up going to NAN. It isn't because of the dates I'm giving because if I shut down the browser (Chrome) and stop Apache and MySql sessions and start them back up and retype in the same date it will work. But then as I go back to enter a different date I eventually get NAN. It will go to NAN after entering 2 to 3 dates. Here is the code:
function calculate_balance($due_date) {
// calculate the balance due for each person based on the due date given
$payment_history = get_last_payment_all();
// hold the balance for each person
$balance = array();
foreach ($payment_history as $history) {
$last_due_date = new DateTime($history['nextDateDue']);
// determine the span (number of days) between due date given
// and last due date on record.
$span = $last_due_date->diff($due_date);
if ($last_due_date == $due_date) {
// if the two dates are equal the balance is the amount in the database.
$balance[] = $history['amount_due'];
} else if ($span->format('%R') == '-') {
// if the last due date on record is greater than the due date given
// the person is at least paid up to this date so balance = 0.
$balance[] = 0.0;
} else {
echo "<b>".$history['lastName']."</b><br />";
echo "last_due_date".$last_due_date->format('m/d/Y')."<br />";
echo "due_date".$due_date->format('m/d/Y')."<br />";
$num_days = $span->format('%d');
echo "num_days = ".$num_days."<br />";
$num_months = $span->format('%m');
echo "num_months = ".$num_months."<br />";
$days = ($num_months * 30) + $num_days;
echo "days = ".$days."<br />";
//$len = strlen($days);
$number_days = intval($days);
echo "num days = ".$number_days."<br />";
// determine the number of pay periods
// (1 pay period = 2 weeks = 14 days)
$twoWeeks = 14;
$num_payperiod = $number_days / $twoWeeks;
echo "Num payperiod = ".$num_payperiod."<br />" ;
// temp balance from last date paid to the due date given
//$rate = floatval($history['biWeeklyRate']);
$temp_bal = $history['biWeeklyRate'] * $num_payperiod;
echo "temp_bal = ".$temp_bal."<br />";
// total balance for this person is their previous balance
// plus the temp_bal
$balance[] = $history['amount_due'] + $temp_bal;
} // if ($history['nextDateDue' > $due_date)
} // foreach ($payment...)
return $balance;
} // function calculate_balance($due_date)
I've put extraneous echos in to help me debug. If I put in 7/1/2011 for a date it will work fine. If I then enter say 6/17/2011 it may or may not work. If it doesn't I shut everything down, start it back up and then enter 6/17/2011 I get the correct values.
It will catch the NAN and recompute $num_payperiod and it works.
Still if someone could shed some light on this I'd appreciate it. I don't like not knowing why I have to it this way.
It has to do with $last_due_date being less than $due_date. If the server is fresh and the browser is fresh it will work the first time...it is repeated calls that it goes hay wire.
function debug ($value = null, $name = '') {
static $dump = '';
if (func_num_args() > 0) {
if ($name != '') {
$dump .= "\$$name = ";
}
$dump .= var_export($value, true) . ";\n";
} else {
$temp = $dump;
$dump = '';
return $temp;
}
}
function calculate_balance ($due_date) {
// Clears the debug cache
debug();
// Adds an entry to the debug cache
debug($due_date, 'due_date');
// calculate the balance due for each person based on the due date given
$payment_history = get_last_payment_all();
debug($payment_history, 'payment_history');
// hold the balance for each person
$balance = array();
$save_debug = false;
foreach ($payment_history as $h => $history) :
debug($h, 'h');
debug($history, 'history');
$last_due_date = new DateTime($history['nextDateDue']);
debug($last_due_date, 'last_due_date');
// determine the span (number of days) between due date given
// and last due date on record.
$span = $last_due_date->diff($due_date);
debug($span, 'span');
if ($last_due_date == $due_date) :
debug(0, 'if');
// if the two dates are equal the balance is the amount in the database.
$balance[] = $history['amount_due'];
elseif ($span->format('%R') == '-') :
debug(1, 'if');
// if the last due date on record is greater than the due date given
// the person is at least paid up to this date so balance = 0.
$balance[] = 0.0;
else :
debug(2, 'if');
$num_days = $span->format('%d');
debug($num_days, 'num_days');
$num_months = $span->format('%m');
debug($num_months, 'num_months');
$days = ($num_months * 30) + $num_days;
debug($days, 'days');
$number_days = intval($days);
debug($number_days, 'number_days');
// determine the number of pay periods
// (1 pay period = 2 weeks = 14 days)
$twoWeeks = 14;
$num_payperiod = $number_days / $twoWeeks;
debug($num_payperiod, 'num_payperiod');
if (is_nan($num_payperiod)) {
$save_debug = true;
}
// temp balance from last date paid to the due date given
//$rate = floatval($history['biWeeklyRate']);
$temp_bal = $history['biWeeklyRate'] * $num_payperiod;
debug($temp_bal, 'temp_bal');
// total balance for this person is their previous balance
// plus the temp_bal
$balance[] = $history['amount_due'] + $temp_bal;
endif;
endforeach;
debug($balance, 'balance');
if ($save_debug) {
// Writes the debug data to a log file
file_put_contents(sprintf('debug_%s.log', microtime(true)), debug());
}
return $balance;
} // function calculate_balance
Whenever $num_payperiod is NAN, a log file will be created.
Yes, if you mean that given a $due_date and a record in the database it will give the same result. What it is doing is if a user enters $due_date = 7/1/2011 and the database has $last_due_date = 6/1/2011 it then calculates the number of days between the two dates, calculates the number of pay periods from the number of days (a pay period is 14 days). Then it determines the next amount due based on the previous balance plus number of pay periods times the rate.
DateInterval::$days is unusually large and always 6015.
$num_days is off by one.
There is rounding where it is not expected on $num_payperiod and $temp_bal.
(I'm currently loading $payment_history with an array of arrays instead of the PDOStatement you are using. I set up a database and connected with PDO, but still get the same results. I should mention I'm on PHP v5.3.1 and v5.3.2.)