【问题标题】:How to display grouped data in separate tables with a PHP loop?如何使用 PHP 循环在单独的表中显示分组数据?
【发布时间】:2019-03-31 21:40:27
【问题描述】:

我是 phpmysqli 的新手。这是我所拥有的以及正在努力实现的目标:我将根据建议进行更新; Database sample data

我想在一个页面上显示数据,并根据每个学生的 sid 为每个学生提供单独的表格。这是我迄今为止尝试过的;

<?php
include_once 'dbcon.php';

$results = $MySQLiconn->query('SELECT * FROM activitybook');

$students = [];

foreach ( $results->fetch_array() as $activity ) {
    $students[$activity['sid']][] = $activity;
}

foreach($students as $sid=>$activities) {
    foreach($activities as $activity) {
         echo
                    "<table><tr>
                        <th>SID</th>
                        <th>Date</th>
                        <th>FName</th>
                        <th>LName</th>
                        <th>activity</th>
                        <th>time</th>
                        <th>score</th>
                        </tr>
                <tr>
                    <td>" . $sid . "</td>
                    <td>" . $activity['fname'] . "</td>
                    <td>" . $activity['lname'] . "</td>
                    <td>" . $activity['activity'] .  "</td>
                    <td>" . $activity['atime'] .  "</td>
                    <td>" . $activity['ascore'] .  "</td>
                </tr></table>";
    }
}
?>

This is what I get

我试图实现的是每个sid 的单独表格。 This is the sample of what I want to archive

【问题讨论】:

  • 您没有代码可以一次又一次地打印表格。你说的表是什么意思?您只想重复行吗?
  • 你缺少 echo 和
  • @Kamal by table 我的意思是在 php 页面上而不是在数据库中,
  • 是的,我明白了,但您没有使用表格标签来重复表格。
  • @mickmackusa,是的,辅助是主键,是的,当学生返回学生时,sid 有重复项,对不起,数据库表名是它的活动簿,让我发布得到的结果和预期结果

标签: php loops html-table grouping mysqli-fetch-array


【解决方案1】:

要求:处理有序的学生记录流。该流由学生记录组组成。每个组由 at 'sid' 列标识。

  • 每个 StudentGroup 都包含在一个 HTML 表格中
  • 每个 StudentRecord 都是表格的一行

我喜欢做的是根据数据构造代码。数据结构如下:

StudentRecordGroup 的迭代

每个 StudentRecordGroup 由以下序列组成:

  • 组进程开始
  • 遍历属于该组的记录
  • 处理组的结束

请注意,此过程中没有条件语句!

现在,我们如何构建代码来做到这一点。您不能使用foreach 循环!这只在循环结束时进行读取。

我们有两个循环:

  • 处理所有记录组的外部循环。
  • 处理一个完整组的内循环。

执行此操作的技术称为“预读”。这就是它所说的。您在开始外循环之前读取了第一条记录。

来源:

Working Code at Pastebin.com

输出:

SID Date    FName   LName   activity    time    score
2   John    Ppap    12  56  56
2   John    Ppap    23  23  23
SID Date    FName   LName   activity    time    score
3   Mito    Mmito   34  12  12
3   Mito    Mmito   45  45  45
SID Date    FName   LName   activity    time    score
4   Uba Uuba    56  78  100

代码:

 <?php // 53020396/how-to-display-grouped-data-in-separate-tables-with-a-php-loop

/* ---------------------------------------------------------------------------
 * The input stream consists of an Ordered Iteration of: 
 *    A collection of Individual Records for each Student (StudentRecordGoup)
 *    
 *  Each StudentRecordGoup consists of a Sequence of:
 *     Start of Group
 *     Iteration of Student records belonging to the group
 *     End of Group
 *
 *   Notice: There is no 'IF' statement anywhere in the control logic for a group! 
 *   
 *   Please note: There is exactly one place in the code to assign any appropriate action! 
 *                i.e. The structure of the code exactly matched the structure of the data. :)   
 * 
 *   This makes it easier to debug, maintain and amend?
 *   
 *   To do this we need 'state' information. Specifically that a record is part 
 *   of the current 'student record group' group or not. How do we do this?
 *    
 *   We always need a record to test! Including at the start! We never read a record
 *   and then decide what to do with it. We always know where we are in the data
 *   structure and either the current record belongs to the group or not. 
 *   
 *    We need to use a technique called 'Read Ahead'. Literally, There is always 
 *    a record to process. You don't have to test it to know where you are. 
 *    Once you process it then you immediately read the next record from the input. 
 *    i.e. You end up reading a new record NOT JUST AT THE WND OF THE LOOP! 
 *    You cannot use 'foreach' loops. 
 *   
 *   We have to include Initialisation to setup code and any termination code.
 *   
 *   I will put all the 'action place holders' in functions. That way it avoids
 *   obscuring the high-level logic.
 */

// Get the ordered student detail records
$pdo = getPdoConnection();
$pdoResultSet = prepareAndExecuteQuery($pdo);


// Process all the students Record Groups  - 'read ahead' of the row  
$curStudentRecord = $pdoResultSet->fetch();  // is assoc array 

while ($curStudentRecord !== false)  { // process the student record groups

   // process one complete student group...
   $curStudentRecordGroupId = $curStudentRecord['sid'];
   startStudendRecordGroup($curStudentRecordGroupId);
   while (   $curStudentRecord !== false  // check record belongs to the current group 
          && $curStudentRecord['sid'] === $curStudentRecordGroupId) {

        processStudentRecord($curStudentRecord);
        $curStudentRecord = $pdoResultSet->fetch();  // read the next record 
    }

   endStudendRecordGroup($curStudentRecordGroupId); // ignore the current record
                                                    // that is the next group!
}
// all groups have been processed
exit;

/* --------------------------------------------------------------------------
 * Student record group processing
 */
function startStudendRecordGroup($curStudentRecordGroupId)
{
    echo "<!-- new group: sid = $curStudentRecordGroupId -->"; 
    echo "<table><tr><th>SID</th><th>Date</th><th>FName</th><th>LName</th>
                     <th>activity</th><th>time</th><th>score</th></tr>";
}

function processStudentRecord($curStudentRecord)
{
    echo "<!-- group record: sid = {$curStudentRecord['sid']} -->";
    echo "<tr>
                    <td>" . $curStudentRecord['sid'] . "</td>
                    <td>" . $curStudentRecord['fname'] . "</td>
                    <td>" . $curStudentRecord['lname'] . "</td>
                    <td>" . $curStudentRecord['col3'] .  "</td>
                    <td>" . $curStudentRecord['col4'] .  "</td>
                    <td>" . $curStudentRecord['col5'] .  "</td>
                </tr>"; 
}

function endStudendRecordGroup($curStudentRecordGroupId)
{
    echo "<!-- end group: sid = $curStudentRecordGroupId -->";
    echo "</table>"; 
}

/* --------------------------------------------------------------------------
 * Database access
 */

// Execute query and return 'resultset'
function prepareAndExecuteQuery(\PDO $pdo)
{
   $sql = 'SELECT id, sid, fname, lname, col3, col4, col5 
           FROM activity
           ORDER BY sid, id';

   $stmt = $pdo->prepare($sql);
   $allOk = $stmt->execute();
   return $stmt;          
}

// DB Connection 
function getPdoConnection()
{
    $opt  = array(
                \PDO::ATTR_ERRMODE            => \PDO::ERRMODE_EXCEPTION,
                \PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC, 
                \PDO::ATTR_EMULATE_PREPARES   => false,
            );

    $pdo = new \PDO('mysql:host=localhost;dbname=notmydb;', 'notme', 'notme', $opt);
    return $pdo;             
}

【讨论】:

    【解决方案2】:

    您需要根据sid 值对结果集数据进行“分组”。在您迭代时,检查您是否正在更改组。

    我还添加了一些改进。

    • 为您的 SELECT 子句中的列命名,以便您只检索您需要的内容。
    • 获取关联数组,而不是索引元素和关联元素的组合。
    • 分配一个临时变量来帮助您确定是继续 sid 组还是开始一个新组(或者如果这是第一次迭代,请不要写 &lt;/table&gt;
    • implode() 有助于消除大量代码膨胀。

    代码:

    $res = $conn->query("SELECT sid, fname, lname, activity, atime, ascore FROM activitybook ORDER BY sid");
    $tmp = null;
    $colheads = ['SID', 'FName', 'LName', 'activity', 'time', 'score'];
    while ($row = $res->fetch_assoc()) {   // don't produce more elements per row than needed
        if ($tmp != $row['sid']) {  // determine if a new group / sid value
            if ($tmp !== null) {
                echo '</table><br>';  // close the previous table
            }
            echo '<table border=1><tr><th>' , implode('</th><th>', $colheads) , '</th></tr>';  // start a new table & add headings
        }
        echo '<tr><td>' , implode('</td><td>', $row) , '</td></tr>';  // display the row data
        $tmp = $row['sid'];   // DUH, I FORGOT TO UPDATE $tmp!
    }
    if ($tmp !== null) {
        echo '</table>';  // close the final table -- so long as there was at least one row in the result set
    }
    

    【讨论】:

      【解决方案3】:

      按 SID 对结果进行分组,然后循环:

      $results = $conn->query('SELECT * FROM activitybook');
      
      $students = []
      
      foreach ( $results->fetch_array() as $activity ) {
          $students[$activity['sid']][] = $activity;
      }
      
      foreach($students as $sid=>$activities) {
          foreach($activities as $activity) {
               echo
                          "<table><tr>
                              <th>SID</th>
                              <th>Date</th>
                              <th>FName</th>
                              <th>LName</th>
                              <th>activity</th>
                              <th>time</th>
                              <th>score</th>
                              </tr>
                      <tr>
                          <td>" . $sid . "</td>
                          <td>" . $activity['fname'] . "</td>
                          <td>" . $activity['lname'] . "</td>
                          <td>" . $activity['activity'] .  "</td>
                          <td>" . $activity['atime'] .  "</td>
                          <td>" . $activity['ascore'] .  "</td>
                      </tr></table>";
          }
      }
      

      给你的一些提示:

      • 使用具有含义名称的变量。你的$row 里面有什么?活动对吗?所以将其命名为$activity。并避免使用$res 之类的缩写。
      • 这同样适用于您的数据库列。 aid 不是一个好习惯。只使用 id 作为主键。此外,sid 应该变为 student_id,这样阅读您的代码的人就会明白它是学生表的外键。

      【讨论】:

      • 感谢您的提示,我会牢记在心,我很容易理解您的代码,但是当我尝试它时,我会为每一行获得单独的表格,其中包含扭曲的数据,就像我在所有列中都有 sid表的,请指教,再次感谢
      • @loem 自从第一个答案以来我已经做了一些调整,请尝试使用当前代码。我是在手机上写的,所以有些错别字。现在我在桌面上,在这里测试了代码并且工作正常。
      • 我仍然得到相同的结果,我已经用截图更新了问题,
      【解决方案4】:

      您可以创建一个单独的学生 id 数组,每次循环检查该 id 是否存在于数组中,而不是创建一个新表,否则创建一个新表。像这样使用:

      <?php
      $res = $conn->query("SELECT * FROM activitybook");
      $sId = [];
      echo "<table>";
      while($row=$res->fetch_array())
      {
          if (count($sId) == 0) {
              $sId[] = $row['sid'];
          }
          if (!in_array($row['sid'], $sId)) {
              $sId[] = $row['sid'];
              echo "</table><table>";
          }
          echo
              "<tr>
                      <th>SID</th>
                      <th>Date</th>
                      <th>FName</th>
                      <th>LName</th>
                      <th>activity</th>
                      <th>time</th>
                      <th>score</th>
                      </tr>
              <tr>
                  <td>" . $row['sid'] . "</td>
                  <td>" . $row['fname'] . "</td>
                  <td>" . $row['lname'] . "</td>
                  <td>" . $row['activity'] .  "</td>
                  <td>" . $row['atime'] .  "</td>
                  <td>" . $row['ascore'] .  "</td>
              </tr>";
      }
      ?>
      

      【讨论】:

      • 刚刚尝试了您的版本,但仍然为数据库表中的每一行获取单独的表,而不是为每个 sid 单独的表。
      猜你喜欢
      • 1970-01-01
      • 2012-06-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-21
      • 2019-04-19
      • 2018-12-25
      • 1970-01-01
      相关资源
      最近更新 更多