【问题标题】:PHP - put the student name and grade into suitable skill namePHP - 将学生姓名和成绩放入合适的技能名称中
【发布时间】:2015-10-01 03:58:37
【问题描述】:

(1)

(2) 学生标记

(3) 技能

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>';
    ?>

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

我快完成了。我可以在 1 行中显示学生姓名和年级。

现在,我最不想做的就是将它们放入合适的技能名称中,如下所示:

我想比较$q2 上的$skillss.skillname

以下是我的逻辑:

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

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

【问题讨论】:

    标签: php html mysql


    【解决方案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>';
    ?>
    

    结果:

    【讨论】:

    • $studentRows[$row['skillName']][$row['className']] 可以写入数组而不是td?
    • @KKLMichael “写入数组而不是 td”是什么意思?
    • 我想要这条线 $studentRows[$row['skillName'][$row['className']] = ''.$row['studentName'].' '.$row['studentGrade'].'';变成 $studentRows[$row['skillName']][$row['className']][] = array($row['studentName'],$row['studentGrade']);我可以吗?
    • @KKLMichael 当然,您可以随意使用我的代码。为什么需要这种改变?
    • @KKLMichael 是的,你可以做出改变。请注意,您还必须修改显示代码。
    【解决方案2】:

    直到设计中第 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

    【讨论】:

    • 我不明白 while($emptyCount)
    • 想想我们刚刚准备输出真实的html表格的点。此时 $memTable 中有什么?它是长度不同的数组的集合。因此,我们通过平行路径遍历这组数组,直到所有三个数组都没有特定元素索引的元素。 Arr1 => [x][x][x][x] Arr2 => [x] Arr3 => [x][x][x] 循环应该只执行到上述数组集的第 4 个元素索引。但是在我的代码中“while ($emptyCount
    • 如果我将 while($emptyCount
    • 代码中应该是 while($emptyCount
    • 您可以通过对照 $currentRow 检查所有数组元素并“中断”循环来防止最终的“while”迭代发生。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多