php中的模数和数组索引问题

时间:2011-02-14 17:09:26

标签: php modulo

我正在尝试从数据库记录创建一个html表。我希望表格宽4个单元格,所以我想我循环的行的数组索引是4的倍数,然后在开头添加一个tr标签。但是,它似乎没有正常工作。谁能帮我吗? (这是CodeIgniter,因此echo锚点等只会创建一个href标记。)

<table width="80%" border="1">
<tr> <!-- create initial tr tag, since we haven't started the loop yet -->
<?php foreach($projects as $index=>$project) : ?>
    <?php echo ((($index + 1) % 4 == 0) ? '<tr>' : ''); ?>
    <td>
    <?php echo anchor('project/view/'.$project->id, $project->project_name, 'title='.$project->project_name); ?>
    </td>
    <?php echo ((($index + 1) % 4 == 0) ? '</tr>' : ''); ?>
<?php endforeach; ?>
 </table>

$ index + 1是因为除以0(数组索引开始)导致错误。我在每一行上回显了$ index + 1的值,如果我在表中有5行,我得到1,2,3,4,5。但是如果$ index + 1那么应该创建tr标记的行不均匀分为4不评估;我正在获得一个不断扩大的单行表。

以下是我希望看到的渲染代码:

<table width="80%" border="1">
  <tr> 
    <td><a href="http://localhost/ignite/index.php/project/view/1" title=Basil's Beatnik Turtle>Basil's Beatnik Turtle</a></td> 
    <td><a href="http://localhost/ignite/index.php/project/view/2" title=Mr. Werewolf Genes>Mr. Werewolf Genes</a></td> 
    <td><a href="http://localhost/ignite/index.php/project/view/3" title=Romeo+Juliet>Romeo+Juliet</a></td> 
    <td><a href="http://localhost/ignite/index.php/project/view/4" title=Basic Hat>Basic Hat</a></td> 
  </tr>
  <tr>
    <!-- I'm not trying to auto-generate empty cells to fill in a final row that contains fewer than 4 at this point, although it would be nice -->
    <td><a href="http://localhost/ignite/index.php/project/view/5" title=Flutterby Hat>Flutterby Hat</a></td> 
  </tr>
</table> 

以下是我实际得到的内容:

<table width="80%" border="1">
  <tr> 
    <td><a href="http://localhost/ignite/index.php/project/view/1" title=Basil's Beatnik Turtle>Basil's Beatnik Turtle</a></td> 
    <td><a href="http://localhost/ignite/index.php/project/view/2" title=Mr. Werewolf Genes>Mr. Werewolf Genes</a></td> 
    <td><a href="http://localhost/ignite/index.php/project/view/3" title=Romeo+Juliet>Romeo+Juliet</a></td> 
  <!-- note the lack of closing </tr> tag on previous chunk - plus it's only 3 cells, not 4 -->

  <tr>
    <td><a href="http://localhost/ignite/index.php/project/view/4" title=Basic Hat>Basic Hat</a></td>
  </tr>
  <!-- this previous chunk has both <tr> and </tr>, but only contains one <td> -->

    <td><a href="http://localhost/ignite/index.php/project/view/5" title=Flutterby Hat>Flutterby Hat</a></td> 
  <!-- the previous chunk is missing both <tr> and </tr> tags, and is only a single cell -->
</table>     
  罗勒的Beatnik龟 Werewolf Genes先生 罗密欧与朱丽叶  上一个块上的标记 - 加上它只有3个单元格,而不是4个单元格 - > 基本帽子  而且,只包含一个 - &gt; Flutterby帽子  和标签,并且只是一个单元格 - &gt;  

我哪里错了?

6 个答案:

答案 0 :(得分:1)

在不知道从SQL查询返回的数据是什么样的情况下,似乎$ index并不是您所期望的那样。

我谦卑地建议这个替代方案:

<?
$count = 1;
foreach($projects as $index=>$project)
{
    if($count % 4 == 0)
    {
         print "</tr><tr>";
    }
    print "<td>" . anchor('project/view/'.$project->id, $project->project_name, 'title='.$project->project_name) . "</td>";
    $count++;
}
?>

答案 1 :(得分:1)

我建议切换到使用计数器变量,同样,你需要重新考虑它的最后一部分,因为除非它以4的倍数结束,否则它也不会给你最终的/ tr。 / p>

这是我如何做到的,我也摆脱了那些可怕的三元运算符:

<table width="80%" border="1">
<?php
$i = 1;
foreach($projects as $index=>$project)
{
    if($i == 1)
    {
          echo '<tr>';
    }

    echo '<td>' . anchor('project/view/'.$project->id, $project->project_name, 'title='.$project->project_name) . '</td>';

    if($i == 4)
    {
          echo '</tr>';
          $i = 0;
    }

    $i++;
} 

if($i != 1) //Catch it if it doesn't end evenly, since $i will == 1 if it ended on a multiple of 4
{
     while($i <= 4) //Create empty cells to even table out, table will quite possibly look funky otherwise 
     {
         echo '<td></td>';
         $i++;
     }
     echo '</tr>'; //End table row
}
?>
 </table>

如果您希望它看起来不错,请将PHP_EOL"\n"附加到每个echo语句的末尾。如果你希望它看起来非常好,你可以将"\t"添加到某些echo语句中,使其具有手动缩进和手动编码的html的外观。

答案 2 :(得分:1)

我喜欢这样的事情的首选解决方案是将其分解为辅助函数(codeigniter details)。它使标记更清洁,并确保在您不必重新考虑它之后解决它。

这是一个裂缝和你所追求的。它将返回一个可以迭代的多维行数组。

function rowify($array, $perRow) {
    $currentRow = 0;
    $counter = 0;
    $new = array();
    foreach ($array as $key => $element) {
        if ($counter % 4 == 0) {
            ++$currentRow;
            $new[$currentRow] = array();
        }
        $new[$currentRow][$key] = $element;
        ++$counter;
    }
    return $new;
}

使用此标记,您的标记将如下所示:

<table width="80%" border="1">
<?php foreach(rowify($projects,4) as $row) : ?>
  <tr>
    <?php foreach ($row as $index=>$project):?>
      <td>
        <?php echo anchor('project/view/'.$project->id, $project->project_name, 'title='.$project->project_name); ?>
      </td>
    <?php endforeach; ?>
  </tr>
<?php endforeach; ?>
 </table>

我觉得这很优雅 - 没有陈述,没有回音'';东西,只是迭代。

答案 3 :(得分:0)

目前,您在每第四个单元格的开头添加一个tr,在每个第四个单元格的末尾添加一个结尾tr。需要在第四个单元格之后添加结束tr,并且应该在第五个之前添加tr。

答案 4 :(得分:0)

考虑一下 - 您使用完全相同的逻辑检查将开头<tr>作为结束</tr>。这意味着每个第4个元素将被一个开始行标记和一个结束行标记包围。

答案 5 :(得分:0)

如果它有帮助 - 这里有一些旧的代码我挖出来做它 - 不是codeigniter但应该引导你 - 已经把我的数据库内容清理干净了:

define('NUMCOLS', 4);
$count = 0;
$counter = 1;
//create table
echo '<table width = \"100%\" border = 1 cellpadding = 0>';
//create a table row for each book   
foreach ($book_array as $row)
{
  // get your data
  if($count % NUMCOLS == 0) //new row
    echo '<tr>';
    echo'<td>';
    // display data
    echo '</td>';
    $count++;
   $counter++;
  if($count % NUMCOLS ==0)
    echo '</tr>'; //end row
}
echo '</table>';
}
}