PHP - 将学生姓名和成绩放入合适的技能名称

时间:2015-10-01 03:58:37

标签: php html mysql

(1)班级
enter image description here
(2) studentmark
enter image description here
(3)技能
enter image description here

PHP代码:

    <?php
    //DB CONNECTION

    //---(1)Get skillname---
    $q = "SELECT skillName FROM skill ORDER BY skillName asc";
    $r = mysqli_query($dbc, $q);
    $num_rows = mysqli_num_rows($r);
    while($row = mysqli_fetch_array($r, MYSQLI_ASSOC))
    {
        $skills[] = $row['skillName'];
    }

    //---(2)Get classname---
    $q1 = "SELECT className FROM class";
    $r1 = mysqli_query($dbc, $q1);
    $num_rows1 = mysqli_num_rows($r1);
    while($row1 = mysqli_fetch_array($r1, MYSQLI_ASSOC))
    {
        $className[] = $row1['className'];
    }

    //---(3)Create table---
    echo '<table border="1" style="border-collapse: collapse; text-align: center">';
    echo '<tr>';
    for($a = 0; $a < $num_rows; $a++)
    {
        echo '<th colspan="2">'.$skillName[$a].'</th>';
    }
    echo '</tr>';
    for($b = 0; $b < $num_rows; $b++)
    {
        echo '<th>Student Name</th>';
        echo '<th>Grade</th>';
    }
    echo '</tr>';

    //---(4)Get student name and grade---
    for($s = 0; $c < $num_rows1; $c++)
    {
          $q2 = "SELECT GROUP_CONCAT(sm.studentName) as studentName,
                        GROUP_CONCAT(sm.studentGrade) as studentGrade,
                        s.skillName
                 FROM studentmark sm
                 LEFT JOIN skill s ON sm.skillID = s.skillID
                 WHERE sm.className = '".$className[$c]."'
                 GROUP BY s.skillID";
          $r2 = mysqli_query($dbc, $q2);
          $num_rows2 = mysqli_num_rows($r2);

          $value = array();
          while($row2 = mysqli_fetch_array($r2, MYSQLI_ASSOC))
          {
              $value[] = $row2;
          }

          echo '<tr>';
          for($d = 0; $d < $num_rows2; $d++)
          {
               echo '<td>'.$value[$d]['studentName'].'</td>';
               echo '<td>'.$value[$d]['studentGrade'].'</td>';
          }
          echo '</tr>';
    }
    echo '</table>';
    ?>

从上面的代码中,我的输出如下:

enter image description here

我差不多完成了。我可以在一行中显示学生姓名和成绩。

现在,我要做的最后一件事是将它们放入合适的技能名称中,如下所示:

enter image description here

我想比较$skills上的s.skillname$q2

以下是我的逻辑:

    if($value[X]['skillName'] == $skills[X])
    {
         //put student name and grade inside
    }
    else
    {
         //empty cell
    }

但我不知道我应该在哪里打开循环并将我的逻辑放入(4)。有人能帮助我吗?

2 个答案:

答案 0 :(得分:1)

在您的设计中,直到第4步的最后一个循环,您做得很好(尽管可以优化)。

您遇到的问题是,您有一组结果代表其中的每个类的行。现在你需要将它们分散到技能表中,重要的是,不要留下垂直间隙。

解决方案是在内存中的二维数组中进行,然后从中创建表 - 因为内存中的每个单元都可以轻松地与html表中的单元格进行寻址。

内存表将是这样的:

|Skill 1 | Skill 2 | Skill3|
|stdnt 1 |stdnt 2,3|stdnt 4|
|        |         |stdnt 5|

请注意我是如何使用array_search获取特定技能的索引并在array_push中将其用于将学生插入正确的子阵列。然后我把它翻译成HTML表格

我用以下代码替换你的上一个循环:

//This is our memory table. Let's create it and add number of child arrays 
//equal to number of skills.
$memTable = array();    
for ($i = 0; $i <= sizeOf($skills) - 1; $i++) {
    $memTable[$i] = array();
}

//Lets spread out your student information in to this 2d array now  
foreach ($value as $student) {

    //Get the index of the skill
    $skillIndex = array_search($student['skillName'], $skills);

    //Now go to appropriate child array and insert your student there
    array_push($memTable[$skillIndex], $student);        
};


//Lets create the table now

$emptyCount = 0;
$currentRow = 0;

//Do until all the skill arrays are empty for a row
while ($emptyCount < 3) {

    echo "<tr>";

    $emptyCount = 0;

    foreach ($memTable as $skillLevel) {

        if (sizeof($skillLevel) - 1 < $currentRow) {

            $emptyCount ++;

            echo "<td>&nbsp</td>";
            echo "<td>&nbsp</td>";

        }
        else {

            echo "<td>" . $skillLevel[$currentRow]['studentGrade'] . "</td>";
            echo "<td>" . $skillLevel[$currentRow]['studentGrade'] . "</td>";  

        }
    }

    $currentRow++;

    echo "</tr>";
};    

请注意,技能将根据$ skills数组中的顺序呈现在表格中。如果您有任何不清楚的地方,请向我提问。您可能需要调整一些字符串名称以采用您的代码。

更新

while($ emptyCount&lt; sizeof($ skills))更准确。

答案 1 :(得分:1)

因此,为了不多次循环数据,我确实搞乱了你干净利落的代码。我还显示了类似名称的原因,这似乎是有用的信息。

我更改了一些变量名称,因为我发现更容易记住每个变量的用途。另外,请注意学生信息查询仅执行一次。 Normaly(读:我不能想到你不会,但我不是CMA),你想减少查询数据库的次数

以下代码将替换您发布的整个脚本。

<?php
//DB CONNECTION
$dbc = // magic connection sauce you already have

// get skills and stash how many there are
$q_class = "SELECT skillName FROM skill ORDER BY skillName asc";
$r_class = mysqli_query($dbc, $q_class);
$num_skills = mysqli_num_rows($r_class);
// start table code so that we can echo the skillname headers
echo '
<table border="1" style="border-collapse: collapse; text-align: center">
    <thead>
        <tr>
            <th rowspan=2>Classes</th>';//header for class name column
$header = array();
while($row = mysqli_fetch_array($r_class, MYSQLI_ASSOC))
{
    $skills[] = $row['skillName'];
    // store both thead rows at the same time so that we can echo them out properly later
    $header['first'][] = '
            <th colspan="2">' . $row['skillName'] . '</th>';
    $header['second'][] = '
            <th>Student Name</th>
            <th>Grade</th>';
}
echo '
        ' . implode($header['first']) . '
        </tr>
        <tr>' . implode($header['second']) . '
        </tr>';
// clean-up
mysqli_free_result($r_class);

// get class names and stash how many there are
$classes = array();
$query_class = "SELECT className FROM class";
$r_class = mysqli_query($dbc, $query_class);
$num_classes = mysqli_num_rows($r_class);
while($row = mysqli_fetch_array($r_class, MYSQLI_ASSOC))
{
    $classes[] = $row['className'];
}
// clean-up
mysqli_free_result($r_class);

echo '
    </thead>
    <tbody>';

// pull query out of loop so that you'll only have to execute it once.
$studentInfoQuery = "
SELECT
    GROUP_CONCAT(sm.studentName) as studentName,
    GROUP_CONCAT(sm.studentGrade) as studentGrade,
    s.skillName,
    sm.className
FROM studentmark sm
LEFT JOIN skill s ON sm.skillID = s.skillID
GROUP BY sm.className,s.skillID";
$r_students = mysqli_query($dbc,$studentInfoQuery);
$num_studentRows = mysqli_num_rows($r_students);
$studentRows = array();

while($row = mysqli_fetch_array($r_students, MYSQLI_ASSOC)) {
    // with our query, we only find 1 cell-pair per skill per class
    $studentRows[$row['skillName']][$row['className']] = '
            <td>' . $row['studentName'] . '</td>
            <td>' . $row['studentGrade'] . '</td>';
}
// everybody do their share! // actually, more clean-up
mysqli_free_result($r_students);

for($j = 0; $j < $num_classes; $j++) {
    echo "
        <tr>
            <th>" . $classes[$j] . "</th>";
    for($i = 0; $i < $num_skills; $i++) {
        // always echo out a cell, even if we have student info for it
        // example: if(isset($studentRows['Listening']['1A'])) echo it out else echo cell
        if(isset($studentRows[$skills[$i]][$classes[$j]]))
            echo $studentRows[$skills[$i]][$classes[$j]];
        else
            echo "
            <td colspan=2>No skill-class-student value</td>";
    }
    echo "
        </tr>";
}

echo '
    </tbody>
</table>';
?>

结果:

Results of code