Leo Sutton Leo Sutton - 3 years ago 63
PHP Question

Why wont my PHP echo output as expected?

I am trying to use a PHP echo to build a table on this page http://www.trackmymarks.com/teacher_analysis.php?year=7&class=7L/Sc1. Unfortunately, the echo command is not working as expected and I have no idea why. It seems to be failing to concatenate the strings correctly.

On line 120, the code fails to produce the necessary tags to format the table as I want it. Here is the PHP for the page:

<?php
require "requires.php";
require "header.php";

echo "<title>TrackMyMarks - Teacher Analysis</title>";

$year = htmlspecialchars($_GET["year"]);
$class = htmlspecialchars($_GET["class"]);

echo "<h1>Teacher Analysis ".$class."</h1>";

if ((int)date("M") < 9) { $academicyear = date("Y") - 1; } else { $academicyear = date("Y"); }


$query = "SELECT * FROM Student INNER JOIN `Year ".$year."` ON Student.UPN = `Year ".$year."`.UPN AND Student.CurrentClass='".$class."' AND `Year ".$year."`.`Year Taken` = '" . $academicyear . "'";

echo $query;

$result = mysqli_query($GLOBALS["con"], $query);
if (!$result)
{
logwrite("MYSQL ERROR: " . mysqli_error($GLOBALS["con"]));
}

$retention = array(array(), array(), array(), array(), array(), array());
$PPIretention = array(array(), array(), array(), array(), array(), array());
$nPPIretention = array(array(), array(), array(), array(), array(), array());
$girlsretention = array(array(), array(), array(), array(), array(), array());
$boysretention = array(array(), array(), array(), array(), array(), array());

while($row = mysqli_fetch_array($result)){
// print_r($row);

if ($year == 7)
{
$TGLookup = "Year7_TG";
} else {
$TGLookup = "Year8_TG";
}

print_r($row);

$targetCredits = lookup($row['Target Level'], $TGLookup);

$studentRetention = array($row['Term 1 Mastery Test'] - $targetCredits, $row['Term 2 Mastery Test'] - $targetCredits, $row['Term 3 Mastery Test'] - $targetCredits, $row['Term 4 Mastery Test'] - $targetCredits, $row['Term 5 Mastery Test'] - $targetCredits, $row['Term 6 Mastery Test'] - $targetCredits);

array_push($retention[0], $studentRetention[0]);
array_push($retention[1], $studentRetention[1]);
array_push($retention[2], $studentRetention[2]);
array_push($retention[3], $studentRetention[3]);
array_push($retention[4], $studentRetention[4]);
array_push($retention[5], $studentRetention[5]);

if ($row['PPI'] == 1) {
array_push($PPIretention[0], $studentRetention[0]);
array_push($PPIretention[1], $studentRetention[1]);
array_push($PPIretention[2], $studentRetention[2]);
array_push($PPIretention[3], $studentRetention[3]);
array_push($PPIretention[4], $studentRetention[4]);
array_push($PPIretention[5], $studentRetention[5]);
} else {
array_push($nPPIretention[0], $studentRetention[0]);
array_push($nPPIretention[1], $studentRetention[1]);
array_push($nPPIretention[2], $studentRetention[2]);
array_push($nPPIretention[3], $studentRetention[3]);
array_push($nPPIretention[4], $studentRetention[4]);
array_push($nPPIretention[5], $studentRetention[5]);
}

if ($row['Gender'] == 'F') {
array_push($girlsretention[0], $studentRetention[0]);
array_push($girlsretention[1], $studentRetention[1]);
array_push($girlsretention[2], $studentRetention[2]);
array_push($girlsretention[3], $studentRetention[3]);
array_push($girlsretention[4], $studentRetention[4]);
array_push($girlsretention[5], $studentRetention[5]);
} else {
array_push($boysretention[0], $studentRetention[0]);
array_push($boysretention[1], $studentRetention[1]);
array_push($boysretention[2], $studentRetention[2]);
array_push($boysretention[3], $studentRetention[3]);
array_push($boysretention[4], $studentRetention[4]);
array_push($boysretention[5], $studentRetention[5]);
}


}

echo '

<div class="row">
<table class="table table-boardered">
<thead>
<tr>
<th>Term</th>
<th>Average Retention</th>
<th>HW Completion percentage</th>
<th>PPI Gap</th>
<th>Gender Gap</th>
</tr>
</thead>
<tbody>
<tr>
<td>Overall</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>';

for ($i = 0; $i < 6; $i++){
if (count($retention[$i]) == 0) {$retentionAverage = 0;} else {$retentionAverage = array_sum($retention[$i])/count($retention[$i]);}
if (count($PPIretention[$i]) == 0) {$PPIretentionAverage = 0;} else {$PPIretentionAverage = array_sum($PPIretention[$i])/count($PPIretention[$i]);}
if (count($nPPIretention[$i]) == 0) {$nPPIretentionAverage = 0;} else {$nPPIretentionAverage = array_sum($nPPIretention[$i])/count($nPPIretention[$i]);}
if (count($boysretention[$i]) == 0) {$boysretentionAverage = 0;} else {$boysretentionAverage = array_sum($boysretention[$i])/count($boysretention[$i]);}
if (count($girlsretention[$i]) == 0) {$girlsretentionAverage = 0;} else {$girlsretentionAverage = array_sum($girlsretention[$i])/count($girlsretention[$i]);}

echo $retentionAverage;

echo '<tr><td>'. ($i + 1) .'</td><td>'. $retentionAverage .'</td><td>'. $PPIretentionAverage-$nPPIretentionAverage .'</td><td>'.' '.'</td><td>'. $girlsretentionAverage-$boysretentionAverage .'</td></tr>';
}
echo '
</tbody>
</table>

';

include "footer.php";
?>

Answer Source

The problem is in the line:

echo '<tr><td>'. ($i + 1) .'</td><td>'. $retentionAverage .'</td><td>'. $PPIretentionAverage-$nPPIretentionAverage .'</td><td>'.' '.'</td><td>'. $girlsretentionAverage-$boysretentionAverage .'</td></tr>';

The arithmetic + and - operators have the same precedence as the string concatenation operator (.) and all of them are associative from left to right.

This means the subexpression in parentheses ($i + 1) is evaluated first and then it is used to compute the rest of the string. All goes well until it reaches:

.'</td><td>'. $PPIretentionAverage-$nPPIretentionAverage

Because of equal precedence and left-to-right associativity, the already computed string is concatenated with </td><td> and then with $PPIretentionAverage (after it is converted to string). The resulted string is then used as the left operator of the the arithmetic subtraction -$nPPIretentionAverage.

The same thing happens again on . $girlsretentionAverage-$boysretentionAverage.

To fix it use parentheses around the arithmetic operators (or extract the arithmetic subexpressions into variables that are computed before the echo()):

echo '<tr><td>'. ($i + 1) 
     .'</td><td>'. $retentionAverage 
     .'</td><td>'. ($PPIretentionAverage - $nPPIretentionAverage)
     .'</td><td>'.' '
     .'</td><td>'. ($girlsretentionAverage - $boysretentionAverage)
     .'</td></tr>';
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download