【问题标题】:Change background color of a cell when next value is different from the preceding one当下一个值与前一个值不同时更改单元格的背景颜色
【发布时间】:2021-10-30 00:02:40
【问题描述】:

我已经在 Stack 上工作多年,但这是我第一次发帖。我正在开发一个网站(php + mysql),下面的问题让我非常抓狂。

我有一个包含 2 列的表格:大小和数量。该表是由一个基本的 php 脚本生成的,它只是将存储在数据库中的值作为表中的行输出。超级基本,没有花哨的东西:

SELECT Size, Amount FROM database WHERE product = 'product123' ORDER BY Size ASC

php echo 输出一个显示大小和相应可用包(数量)的 html 表。

Echo '<td>'.$record['size'].'</td><td>'.$record['amount'].'</td>'

某些尺码有不同的数量,因此特定尺码可能会出现多次。示例:

Size | Amount
1    | 10
1    | 50
2    | 10
2+   | 10
3    | 40
3+   | 25
3+   | 40
4+   | 25

我想要实现的是包含相同尺寸的行具有相同的背景颜色。所以它应该交替,按尺寸分组,不幸的是这是不规则的。示例:

Size | Amount
1    | 10     < yellow
1    | 50     < yellow
2    | 10     < transparent
2+   | 10     < yellow
3    | 40     < transparent
3+   | 25     < yellow
3+   | 40     < yellow
4+   | 25     < transparent

因此,如果下一个 Size 与前一个不同,则行背景颜色应该改变。这样,单个尺寸作为一个组交替突出显示。请注意,尺寸 2 和 2+(3 和 3+ 相同)被认为是不同的尺寸,因此背景颜色应该改变。

我不知道如何用 php 实现这一点。困难在于我不能使用基于奇数/偶数的评估,因为有时会涉及“+”,并不是所有的 Sizes 数值。 不幸的是,更改命名方案以摆脱那个“+”不是一种选择。

我正在考虑以某种方式进行 php 检查,同时逐行生成表格,如果下一个输出的大小与前一个相同。如果是:背景颜色没有变化。如果否:更改背景颜色。但是我不知道最好的方法是编写这样的代码。任何指向正确方向的指针都非常感谢。

【问题讨论】:

  • 所以 size 是 varchar 吗?是什么决定了实际颜色是什么?
  • 你几乎可以按照你所说的去做,如果它们按大小排序,你只需检查以前是否与当前相同,如果是,则颜色相同。如果没有,那就换新颜色。您还可以使用循环根据 key 的大小对返回的结果进行分组排序,然后在这些组中再循环一次。也许会内爆以节省更多循环。
  • 是的,它是一个 varchar。我忘了提那个。实际颜色仅由大小的变化驱动。因此,当表中的下一个 Size 与前一个 Size 不同时,应该会发生行颜色更改。
  • 如果你愿意,我只能在mysql中做,否则使用下面的php解决方案
  • 我还不确定最好的路线是什么。您将如何仅使用 mqsql 实现这一目标?

标签: php html mysql


【解决方案1】:

只是一个MCVE

// your data
$records[] = array('size' => "1");
$records[] = array('size' => "1");
$records[] = array('size' => "2");
$records[] = array('size' => "2+");
$records[] = array('size' => "3");
$records[] = array('size' => "3+");
$records[] = array('size' => "3+");
$records[] = array('size' => "4");

$lastSize = $records[0]['size'];
$color = "yellow";

foreach ($records as $record) {
    if ($lastSize != $record['size']) {
        $lastSize = $record['size'];
        if ($color == "yellow") $color = "transparent";
        else $color = "yellow";
    }
    $lastSize == $record['size'];
    echo $record['size'].' - '.$color.'<br>';
}

// OUTPUT:
// 1 - yellow
// 1 - yellow
// 2 - transparent
// 2+ - yellow
// 3 - transparent
// 3+ - yellow
// 3+ - yellow
// 4 - transparent

【讨论】:

    【解决方案2】:

    好的,我们将从最后开始。你可能想把你的颜色放在&lt;tr&gt; 上。最简洁的方法是使用 css 类。

    if ($newSize) {
        echo '<tr class="tranparentRow">';
    } else {
        echo '<tr class="yellowRow">';
    }
    

    稍后我们将弄清楚如何将正确的值放入$newSize。接下来,我们需要上面类的 css,所以请确保它在您的样式中:

    .transparentRow {
        background-color: transparent;
    }
    .yellowRow {
        background-color: yellow;
    }
    

    好的,让我们把+ 去掉大小:

    $plainSize = trim($record['size'], '+')
    

    好的,我们使用它进行比较,使用不断变化的$oldSize 变量。这是一个完整的功能块:

    $oldSize = 0;
    foreach($whatever as $record) {
        $plainSize = trim($record['size'], '+')
        if ($plainSize == $oldSize) {
            $newSize = false;
        } else {
            $newSize = true;
        }
        $oldSize = $plainSize;
    
        if ($newSize) {
            echo '<tr class="tranparentRow">';
        } else {
            echo '<tr class="yellowRow">';
        }
    
        echo '<td>'.$record['size'].'</td><td>'.$record['amount'].'</td>';
        echo '</td>';
    }
    

    一些清理可能会导致这种情况:

    $oldSize = 0;
    foreach($whatever as $record) {
        $plainSize = trim($record['size'], '+')
        if ($plainSize == $oldSize) {
            echo '<tr class="tranparentRow">';
        } else {
            echo '<tr class="yellowRow">';
        }
        $oldSize = $plainSize;
    
        echo '<td>'.$record['size'].'</td><td>'.$record['amount'].'</td>';
        echo '</td>';
    }
    

    我希望这不仅有助于解决这个问题,还希望通过一个示例来说明如何解决许多其他问题。从头开始,从头再来。

    【讨论】:

      【解决方案3】:

      正如我的评论所建议的,使用双 foreach() + implode() (还有另一种解决方案)

      <?php
      $array[]    =   array("size"=>1,"amount"=>50);
      $array[]    =   array("size"=>2,"amount"=>10);
      $array[]    =   array("size"=>"2+","amount"=>10);
      $array[]    =   array("size"=>3,"amount"=>40);
      $array[]    =   array("size"=>"3+","amount"=>25);
      $array[]    =   array("size"=>"3+","amount"=>40);
      $array[]    =   array("size"=>"3+","amount"=>25);
      $array[]    =   array("size"=>'4+',"amount"=>30);
      
      // Sort by size
      foreach($array as $row) {
              $new[$row['size']][]    =   $row['amount'];
          }
      ?>
          <table>
      <?php
          $i = 0;
          // Loop through the sorted groups
          foreach($new as $size => $amts) {
              // Determine odd or even
              $color = ($i % 2 == 0)? "yellow":"transparent";
      ?>      <tr>
                  <td class="<?php echo $color; ?>"><?php echo $size; ?></td>
                  <td class="<?php echo $color; ?>"><?php echo implode("</td>".PHP_EOL."</tr>".PHP_EOL."<tr>".PHP_EOL.'<td class="'.$color.'">'.$size.'</td><td class="'.$color.'">',$amts); ?></td>
              </tr>
      <?php       $i++;
              }
      ?>
          </table>
      

      【讨论】:

        【解决方案4】:

        您可以使用像这样的 php 会话来做到这一点

          session_start();
            $_SESSION["pre_val"]='not set';
            $_SESSION["pre_class"]='transparent';
        
        //in your loop for showing table
        //your loop starts
          if($_SESSION["pre_val"]==$record['size']){
            $suitable_class=$_SESSION["pre_class"];
          }
          else{
               if($_SESSION["pre_class"]=='yellow'){$suitable_class='transparent';}
               else{$suitable_class='yellow';} 
        
           }
        //setting current values to session
        $_SESSION["pre_class"] = $suitable_class;
        $_SESSION["pre_val"]   = $record['size'];
        
        Echo '<tr class="$suitable_class"><td>'.$record['size'].'</td><td>'.$record['amount'].'</td></tr>';
        //your loop ends
        

        在你的 CSS 中

        .yellow{background-color:yellow;}
        .transparent{ background-color: rgba(255, 0, 0, 0.5);}
        

        希望这能解决您的问题

        【讨论】:

          【解决方案5】:

          打印表格时的一些 for 循环乐趣

          $rows = array(
              array("size"=>"1" ,"amount"=>"10"),
              array("size"=>"1" ,"amount"=>"50"),
              array("size"=>"2" ,"amount"=>"10"),
              array("size"=>"2+","amount"=>"10"),
              array("size"=>"3" ,"amount"=>"40"),
              array("size"=>"3+","amount"=>"25"),
              array("size"=>"3+","amount"=>"40"),
              array("size"=>"4+","amount"=>"25")
          );
          
          echo "
          <table>
              <thead>
                  <tr><th>Size</th><th>Amount</th></tr>
              </thead>
              <tbody>";
          $bgColors = ['transparent','yellow'];
          $bgColor = 0;
          echo "
                  <tr>
                      <td class='" . $bgColors[$bgColor] . "'>" . $rows[0]["size"] . "</td><td>" . $rows[0]["amount"] . "</td>
                  </tr>";
          for($i = 1, $max = count($rows), $lastSize = $rows[0]; $i < $max; $lastSize = $rows[$i], $i++) {
              if($rows[$i]["size"] !== $lastSize["size"])
                  $bgColor = ($bgColor + 1) % 2;
              echo "
                  <tr>
                      <td style='background-color:" . $bgColors[$bgColor] . "'>" . $rows[$i]["size"] . "</td><td>" . $rows[$i]["amount"] . "</td>
                  </tr>";
          }
          echo "
              </tbody>
          </table>";
          

          还有一个不请自来的 JS 解决方案(假设您已经像往常一样打印出表格)

          var rows = document.querySelectorAll('#sizeTable tbody td[name=size]');
          var bgColors = ['transparent','yellow'];
          var bgColor = 0;
          
          for(var i = 1, lastSize = rows[0], max = rows.length; i < max; lastSize = rows[i],i++) {
              if(rows[i].innerHTML !== lastSize.innerHTML) {
                  bgColor = (bgColor + 1) % 2;
              }
              rows[i].style['background-color'] = bgColors[bgColor];
          }
          

          【讨论】:

            【解决方案6】:

            您可以将当前大小保留在变量上,如果它发生变化,您可以更改颜色。

                <html>
            <head><title> Sample - Menukz </title></head>
            <body>
            <?php
                /* Sample data array with size and amount */
                $product['product123'] = array
                              (
                              array("size"=>"1", "amount"=>10),
                              array("size"=>"1", "amount"=>50),
                              array("size"=>"2", "amount"=>10),
                              array("size"=>"2+", "amount"=>10),
                              array("size"=>"3", "amount"=>40),
                              array("size"=>"3+", "amount"=>25),
                              array("size"=>"3+", "amount"=>40),
                              array("size"=>"4+", "amount"=>25)
                              );
            
                $pre_size=0;
                $pre_init=1;
            
                echo "<table>";
            
                foreach($product['product123'] as $row)
                {
                    echo "<tr>";
                    /* Initialize */
                    if(strcmp($pre_size, $row['size']) !== 0 && $pre_init ===1)
                    {
                        $pre_size = $row['size'];
                        $pre_init = 0;
                    }
                    /* Change track */
                    if (strcmp($pre_size, $row['size']) !== 0 && $pre_init ===0)
                    {
                        echo "<td>Changed ... </td><td>".  $row['size'] . "</td><td>" . $row['amount'] . "</td>"; 
                        $pre_size = $row['size'];
                    }
                    else
                    {
                        echo "<td>Not Changed ... </td><td>".  $row['size'] . "</td><td>" . $row['amount'] . "</td>";           
                    }
                    echo "</tr>";
                }   
            ?>
            </body>
            </html>
            

            【讨论】:

            • 我无法让这个与用于从数据库中获取记录的 while 循环一起工作。每次获取记录时,$record['size'] 总是重置为要从数据库中提取的下一个值。所以 $current_size 和 $record['size'] 总是相同的。还是我在这里遗漏了什么?
            【解决方案7】:

            感谢大家提出的解决方案。 Berriel 的 MCVE 就像一个魅力!但是 Stack 还没有让我 +1 答案。

            我还有一个问题: 我还有第二个表,其中第一列的输出可以是由 10 个限制为 [a-z][0-9] 的字符组成的任何文章代码。由于没有像 Size 表中这样的预定义方案,我无法像大多数建议的解决方案那样硬编码/预测任何输出。但是,我仍然想以我在开篇文章中描述的相同方式为行着色。

            我不熟悉mysql中的存储过程或PDO。有没有什么办法可以绕过预定义内容的数组,并且仍然可以使用相同的文章代码实现行的颜色分组?

            【讨论】:

              【解决方案8】:

              您可以使用嵌套的重复区域来完成此操作。

              首先按组选择您的产品WHERE product = 'product123' GROUP BY size

              <?php
              require ('conn.php');
              try {
                  $prod = 'product123';
                  $sql = "SELECT * FROM sizes WHERE product=:prod GROUP BY size";
                  $query = $conn->prepare($sql);
                  $query->bindValue(':prod', $prod, PDO::PARAM_INT);
                  $query->execute();
                  $row = $query->fetch(PDO::FETCH_ASSOC);
                  $totalRows = $query->rowCount();
              } catch (PDOException $e) {
                  die('failed!');
              }
              ?>
              

              然后在嵌套重复区域内按数量排序每组中的所有产品。

              每个“分组行”都会交替显示颜色。

              <table width="200" border="0" cellspacing="0" cellpadding="5">
                <tr>
                  <td>Size</td>
                  <td>Amount</td>
                </tr>
                <?php
                $i = 0;
                do {
                  $i = $i + 1;
                  if ($i % 2 == 0){
                  echo '<tr bgcolor=#E4E4E4><td colspan="2">';
                      } else {
                  echo '<tr bgcolor=#EEEEEE><td colspan="2">';
                  }
                try {
                  $group = $row['size'];
                  $sql = "SELECT * FROM sizes WHERE size=:group ORDER BY amount ASC";
                  $nested = $conn->prepare($sql);
                  $nested->bindValue(':group', $group, PDO::PARAM_INT);
                  $nested->execute();
                  $row_nested = $nested->fetch(PDO::FETCH_ASSOC);
                  $totalRows_nested = $nested->rowCount();
              } catch (PDOException $e) {
                  die('nested failed');
              }
                echo '<table border="0" cellpadding="0" cellspacing="0" width="200">';
                do {
                    echo '<tr><td width="100">'.$row_nested['size'].'</td><td width="100">'.$row_nested['amount'].'</td></tr>';
                } while ($row_nested = $nested->fetch(PDO::FETCH_ASSOC));
                echo '</table>';
                echo '</td></tr>';
                } while ($row = $query->fetch(PDO::FETCH_ASSOC));
                ?>
              </table>
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2016-12-31
                • 2011-08-16
                • 2017-03-11
                • 1970-01-01
                • 2012-09-03
                • 1970-01-01
                • 2012-09-30
                • 1970-01-01
                相关资源
                最近更新 更多