php foreach 循环中的 HTML 表格,其中仅当元素等于表格列标题名称时才会填充单元格数据

Posted

技术标签:

【中文标题】php foreach 循环中的 HTML 表格,其中仅当元素等于表格列标题名称时才会填充单元格数据【英文标题】:HTML table in php foreach loop where the cell data is only populated if an element is equal to the table column head name 【发布时间】:2021-10-09 04:42:00 【问题描述】:

我使用以下方法在表格中创建了列标题:

if (count($round) > 0): ?>
<table>
  <thead>
    <tr>
<?php foreach ($round as $colhead): array_map('htmlentities', $colhead); ?>
      <th><?php  echo implode('</th><th>',$colhead); ?></th>
    </tr>
<?php endforeach; endif;
?>
  </thead>

$round 是:

Array
(
    [0] => Array
        (
            [32] => -7
            [31] => -6
            [29] => -5
            [27] => -4
            [23] => -3
            [19] => -2
            [17] => -1
            [0] => 1
            [2] => 2
            [10] => 3
            [14] => 4
            [16] => 5
            [33] => 6
        )

)

这正是我想要的结果,因为 $round 不会总是产生相同数量的列。

我想要在这些标题下方的表格行中的数据只需要包含列标题名称的那些项目。

假设列标题是: | -7 | -6 | -5 | -4 | -3 | -2 | -1 | 1 | 2 | 3 | 4 | 5 | 6 | 基于上面的foreach 循环。

我使用以下内容在下一行填充我的第一列:

<tbody>
    <tr>
      <td>
  <?php foreach ($matches as $match)  
$firstCharacter = $match['match']['scores_csv'][0];
$lastCharacter = $match['match']['scores_csv'][-1]; 
$id1 = $match['match']['player1_id'];
$id2 = $match['match']['player2_id'];
    if ($match['match']['round'] === -7) 
      echo  "Table: ".$match['match']['player1_votes']."</br>".$participants[$id1]["name"].$participants[$id1]['misc'].": ".$firstCharacter. "</br>".$participants[$id2]["name"].$participants[$id2]['misc'].":".$lastCharacter. "</br>";
  
  ?>
    </td>
   </tr>
  </tbody>
</table>

虽然它有效,但这只是因为我知道表中第一列的标题是 -7。我试图弄清楚如何仅根据列标题显示与我的列标题相同的那些项目以显示在下一行中,以便我可以执行另一个 foreach 循环来显示我的表格的其余部分。所以基本上,我需要做什么,而不是上面的 -7?我完全画了一个空白。

$match['match']['round'] 等于列标题。下面是一个小样本 $matches 以防万一。

 ["match":"id":246811883,"tournament_id":10128202,"state":"complete","player1_id":152239163,"player2_id":152239166,"player1_prereq_match_id":null,"player2_prereq_match_id":null,"player1_is_prereq_match_loser":false,"player2_is_prereq_match_loser":false,"winner_id":152239166,"loser_id":152239163,"started_at":"2021-08-07T01: 59: 51.967+02: 00","created_at":"2021-08-07T01: 59: 51.692+02: 00","updated_at":"2021-08-07T02: 22: 29.417+02: 00","identifier":"A","has_attachment":false,"round":1,"player1_votes":1,"player2_votes":null,"group_id":null,"attachment_count":null,"scheduled_time":null,"location":null,"underway_at":"2021-08-07T02: 05: 31.834+02: 00","optional":false,"rushb_id":null,"completed_at":"2021-08-07T02: 22: 29.455+02: 00","suggested_play_order":null,"forfeited":null,"open_graph_image_file_name":null,"open_graph_image_content_type":null,"open_graph_image_file_size":null,"prerequisite_match_ids_csv":"","scores_csv":"0-2","match":"id":246811884,"tournament_id":10128202,"state":"complete","player1_id":152239594,"player2_id":152239168,"player1_prereq_match_id":null,"player2_prereq_match_id":null,"player1_is_prereq_match_loser":false,"player2_is_prereq_match_loser":false,"winner_id":152239594,"loser_id":152239168,"started_at":"2021-08-07T01: 59: 51.984+02: 00","created_at":"2021-08-07T01: 59: 51.698+02: 00","updated_at":"2021-08-07T02: 32: 30.655+02: 00","identifier":"B","has_attachment":false,"round":1,"player1_votes":2,"player2_votes":null,"group_id":null,"attachment_count":null,"scheduled_time":null,"location":null,"underway_at":"2021-08-07T02: 05: 23.667+02: 00","optional":false,"rushb_id":null,"completed_at":"2021-08-07T02: 32: 30.690+02: 00","suggested_play_order":null,"forfeited":null,"open_graph_image_file_name":null,"open_graph_image_content_type":null,"open_graph_image_file_size":null,"prerequisite_match_ids_csv":"","scores_csv":"2-1"]

我尝试使用以下方法重新索引数组:

$matchesa = array_column($matches, 'match');
$matchesa = array_column($matchesa, null, 'round');

foreach ( $matches as $match )  
            $id1 = $match['match']['round'];
 
        echo $matchesa[$id1]['round'].PHP_EOL;
    
  

想要的输出是这样的:

【问题讨论】:

你需要根据$round数组重构$matches数组。使用$round 值作为键并从$matches 获取数据。使其成为一个新数组。这只会给你$round 值的数据,然后不需要比较。直接去foreach就行了 另外,如果你可以控制从数据库中获取数据(通过它创建$matches),那么你可以只在那里进行索引。它会让事情变得更简单。 @AnantKumarSingh 我试图索引 $matches,但现在我被困在那里。还有什么想法吗? 你能用 json_encode($matches) 代替 var_dump 或 print_r 给我们你的匹配吗 我已经进行了编辑 【参考方案1】:

前面几个cmets:

您的 $round 数组只有一个元素,但您有一个 foreach 语句迭代“所有”元素...

foreach ($round as $colhead): array_map('htmlentities', $colhead);

... 这在语义上没有多大意义,因为一个表不应该有多个标题。然后在$colhead 列表上调用array_map,但结果不会保存并稍后使用。此外,由于这些值是整数,因此甚至没有理由将 htmlentities 函数应用于这些值。稍后,当您发布名称等实体时,此功能可能会很有用。

下面的代码在一个整数和索引之间构建一个映射到$matches 数组中,可以在其中找到该整数。然后处理变得大大简化。仅用于演示目的:

    我只为每个匹配输出player1_id 值,这样处理的细节就不会丢失,为了简单起见,我将此值设置为与整数相同。 如果未找到匹配轮次,则表格列仅填充&lt;br&gt;。 另外,为了简单起见,我将$round 数组定义为包含一个元素,一个包含值[-1, -3, -5] 的列表,并且$matches 数组将只包含两个表行的数据。第一行为 -1 和 -5(-3 将丢失),第二行将包含所有三个整数。
<?php
$round = [[-1, -3, -5]];

$match0 = [];
$match0[] = Array('match' => Array('round' => 2, 'player1_id' => 2));
$match0[] = Array('match' => Array('round' => 1, 'player1_id' => 1));
$match0[] = Array('match' => Array('round' => 3, 'player1_id' => 3));
$match0[] = Array('match' => Array('round' => -1, 'player1_id' => -1));
$match0[] = Array('match' => Array('round' => -4, 'player1_id' => -4));
$match0[] = Array('match' => Array('round' => -5, 'player1_id' => -5));
$match0[] = Array('match' => Array('round' => -6, 'player1_id' => -6));

$match1 = [];
$match1[] = Array('match' => Array('round' => -7, 'player1_id' => -7));
$match1[] = Array('match' => Array('round' => -1, 'player1_id' => -1));
$match1[] = Array('match' => Array('round' => -2, 'player1_id' => -2));
$match1[] = Array('match' => Array('round' => -3, 'player1_id' => -3));
$match1[] = Array('match' => Array('round' => -8, 'player1_id' => -8));
$match1[] = Array('match' => Array('round' => 9, 'player1_id' => 9));
$match1[] = Array('match' => Array('round' => -5, 'player1_id' => -5));

$matches = [$match0, $match1];


if (count($round) > 0):
    $round0 = $round[0];
?>
<table>
  <thead>
    <tr>
<?php
    foreach($round0 as $hdr):
?>
      <th><?= $hdr ?></th>
<?php
    endforeach;
?>
    </tr>
  </thead>
  <tbody>
<?php
    foreach ($matches as $match):
        // create mapping between round number and index into $matches:
        $index_map = [];
        $l = count($match);
        for ($i = 0; $i < $l; $i++):
            $matchRound = $match[$i]['match']['round'];
            $index_map[$matchRound] = $i;
        endfor;
?>
    <tr>
<?php
        foreach($round0 as $matchRound):
            if (!array_key_exists($matchRound, $index_map)):
?>
      <th><br></th>
<?php
            else:
                $theMatch = $match[$index_map[$matchRound]]['match']
?>
      <th><?= $theMatch['player1_id'] ?></th>
<?php
            endif;
        endforeach;
    endforeach;
?>
    </tr>
  </tbody>
</table>
<?php
endif;
?>

输出:

<table>
  <thead>
    <tr>
      <th>-1</th>
      <th>-3</th>
      <th>-5</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>-1</th>
      <th><br></th>
      <th>-5</th>
    <tr>
      <th>-1</th>
      <th>-3</th>
      <th>-5</th>
    </tr>
  </tbody>
</table>

【讨论】:

这只会产生第一个匹配,每轮有多个匹配。所需的输出是在列标题下方的行中具有相同整数的所有匹配项。 很抱歉。我已经更新了答案。【参考方案2】:

您已经在$colhead 中拥有所有标题列。

因此,您可以像这样迭代列:

foreach ($matches as $match) 
    $colindex = 0;
    for ($colindex = 0; $colindex < count($colhead), $colindex++) 
        if ($match['match']['round'] === $colhead[$colindex]) 
            //your cell template here
        
    

【讨论】:

根据列标题匹配查找同一行中的所有匹配项。 @JenniferHamilton 编辑了我的答案。如果您在应用这个想法时遇到困难,请告诉我。【参考方案3】:

您可以使用字典来存储基于回合的所有匹配项:

<?php

/*#########SAMPLE DATA########*/

$matches = <<<MATCHES
["match":"id":246811883,"tournament_id":10128202,"state":"complete","player1_id":152239163,"player2_id":152239166,"player1_prereq_match_id":null,"player2_prereq_match_id":null,"player1_is_prereq_match_loser":false,"player2_is_prereq_match_loser":false,"winner_id":152239166,"loser_id":152239163,"started_at":"2021-08-07T01: 59: 51.967+02: 00","created_at":"2021-08-07T01: 59: 51.692+02: 00","updated_at":"2021-08-07T02: 22: 29.417+02: 00","identifier":"A","has_attachment":false,"round":1,"player1_votes":1,"player2_votes":null,"group_id":null,"attachment_count":null,"scheduled_time":null,"location":null,"underway_at":"2021-08-07T02: 05: 31.834+02: 00","optional":false,"rushb_id":null,"completed_at":"2021-08-07T02: 22: 29.455+02: 00","suggested_play_order":null,"forfeited":null,"open_graph_image_file_name":null,"open_graph_image_content_type":null,"open_graph_image_file_size":null,"prerequisite_match_ids_csv":"","scores_csv":"0-2","match":"id":246811884,"tournament_id":10128202,"state":"complete","player1_id":152239594,"player2_id":152239168,"player1_prereq_match_id":null,"player2_prereq_match_id":null,"player1_is_prereq_match_loser":false,"player2_is_prereq_match_loser":false,"winner_id":152239594,"loser_id":152239168,"started_at":"2021-08-07T01: 59: 51.984+02: 00","created_at":"2021-08-07T01: 59: 51.698+02: 00","updated_at":"2021-08-07T02: 32: 30.655+02: 00","identifier":"B","has_attachment":false,"round":1,"player1_votes":2,"player2_votes":null,"group_id":null,"attachment_count":null,"scheduled_time":null,"location":null,"underway_at":"2021-08-07T02: 05: 23.667+02: 00","optional":false,"rushb_id":null,"completed_at":"2021-08-07T02: 32: 30.690+02: 00","suggested_play_order":null,"forfeited":null,"open_graph_image_file_name":null,"open_graph_image_content_type":null,"open_graph_image_file_size":null,"prerequisite_match_ids_csv":"","scores_csv":"2-1"]
MATCHES;

$round = <<<ROUND
[-7, -6, -5, -4, -3, -2, -1, 1, 2, 3, 4, 5, 6]
ROUND;

$matches = json_decode($matches, true);
$round = json_decode($round);


/*###########################*/

//class to define data when we found a match
class MatchInfo 
    public $firstCharacter;
    public $lastCharacter;
    public $player1Votes;
    public $player1Name;
    public $player1Misc;
    public $player2Name;
    public $player2Misc;


$tableHeaders = null;
$matchInfoData = [];
//$participants = [...]

if (!empty($round))  //if we have round
    //get the html for table headers
    $tableHeaders = array_map(function($colHead)
        return "<th>Round: $colHead</th>";
    , $round);
    $tableHeaders = implode("", $tableHeaders);

    //remove item in matches
    while ($match = array_pop($matches)) 
        $targetRound = $match['match']['round'];
        if (!in_array($targetRound, $round)) continue; //skip item if match round is not in our column

        if (!array_key_exists($targetRound, $matchInfoData))  //if we never look at this round before
            $matchInfoData[$targetRound] = []; //initialize array to hold other match based on the round
        


        $id1 = $match['match']['player1_id'];
        $id2 = $match['match']['player2_id'];
        //new up and save off the data
        $matchInfo = new MatchInfo();
        $matchInfo->firstCharacter = $match['match']['scores_csv'][0];
        $matchInfo->lastCharacter = $match['match']['scores_csv'][-1];
        $matchInfo->player1Votes = $match['match']['player1_votes'];
        $matchInfo->player1Name = "Player1 Name"; //$participants[$id1]["name"];
        $matchInfo->player1Misc = "Player1 Misc"; //$participants[$id1]["misc"];
        $matchInfo->player2Name = "Player2 Name"; //$participants[$id2]["name"];
        $matchInfo->player2Misc = "Player2 Misc"; // $participants[$id2]["misc"];

        $matchInfoData[$targetRound][] = $matchInfo; //add data to the round...array_push
    



//if no matches found exit
if (empty($matchInfoData)) 
    echo "No match info";
    exit;


$tableData = '';
//now we loop through all the array to be sure its the same order as the ths
foreach ($round as $td) 
    $columnHtml = '';
    if (array_key_exists($td, $matchInfoData))  //if what we stored contains the targeted column
        //create a td html
        $dataHtmlArray = array_map(function(MatchInfo $curItem)
            return <<<ITEMDATA
    <div class="match-info">
        Table: $curItem->player1Votes <br/>
        $curItem->player1Name $curItem->player1Misc $curItem->firstCharacter <br/>
        $curItem->player2Name $curItem->player2Misc $curItem->lastCharacter  <br/>
    </div>
ITEMDATA;

        ,$matchInfoData[$td]);

        $dataHtml = implode("<br/>", $dataHtmlArray);
        $columnHtml = "<td><div class='match-container'> $dataHtml </div></td>";

    else  //otherwise it needs a blank td to go to next column
        $columnHtml = "<td></td>";
    
    $tableData .= $columnHtml;


?>

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/css/bootstrap.min.css" integrity="sha384-KyZXEAg3QhqLMpG8r+8fhAXLRk2vvoC2f3B09zVXn8CA5QIVfZOJ3BCsw2P0p/We" crossorigin="anonymous">

<table class="table table-bordered">
    <thead>
    <tr><?php echo $tableHeaders; ?></tr>
    </thead>
    <tbody>
    <tr>
        <?php echo $tableData; ?>
    </tr>

    </tbody>
</table>

<style>
    .match-info 
        border: 1px solid #dadde5;
        padding: 24px;
        border-radius: 4px;
    
</style>

【讨论】:

以上是关于php foreach 循环中的 HTML 表格,其中仅当元素等于表格列标题名称时才会填充单元格数据的主要内容,如果未能解决你的问题,请参考以下文章

解释php中的foreach循环[重复]

foreach循环php中的PDOStatement

foreach 循环内的 while 循环仅返回 1 行

PHP foreach循环中的多个索引变量

php foreach循环中的变量

带有HTML的PHP​​简单foreach循环[关闭]