通过PHP循环运行表

时间:2012-09-26 14:08:21

标签: php html arrays loops

我有一个显示类别和子类别列表的表,使用一个函数来遍历父/子树。这是脚本的标记:

<table border="1" width="100%" cellspacing="0" cellpadding="2">
    <tr class="dataTableHeadingRow">
        <td class="dataTableHeadingContent"><?php echo TABLE_HEADING_PRODUCTS; ?></td>
        <td class="dataTableHeadingContent" align="right"><?php echo TABLE_HEADING_TOTAL_WEIGHT; ?>&nbsp;</td>
    </tr>

<?php
function category_list( $category_parent_id = 0 )
{
    // build our category list only once
    static $cats;

    if ( ! is_array( $cats ) )
    {
        $sql  = 'select cd.categories_name,c.categories_id, c.parent_id, c.sort_order from ' . TABLE_CATEGORIES . ' c, ' . TABLE_CATEGORIES_DESCRIPTION . ' cd where c.categories_id = cd.categories_id';
        $res  = tep_db_query( $sql );
        $cats = array();

        while ( $cat = tep_db_fetch_array( $res ) )
        {
            $cats[] = $cat;
        }
    }

    // populate a list items array
    $list_items = array();

    foreach ( $cats as $cat )
    {
        // if not a match, move on
        if ( ( int ) $cat['parent_id'] !== ( int ) $category_parent_id )
        {
            continue;
        }

        // open the list item
        $list_items[] = '<tr class="dataTableRow">';
        $list_items[] = '<td class="dataTableContent"><li>';

        // construct the category link

        $list_items[] = $cat['categories_name'];

        // recurse into the child list
        $list_items[] = category_list( $cat['categories_id'] );

        // close the list item
        $list_items[] = '</li></td>';
        $list_items[] = '</tr>';
    }

    // convert to a string
    $list_items = implode( '', $list_items );

    // if empty, no list items!
    if ( '' == trim( $list_items ) )
    {
        return '';
    }

    // ...otherwise, return the list
    return '<ul>' . $list_items . '</ul>';
}  

echo category_list();
?>
        <td class="dataTableContent"></td>
</table>

目前此处正确打印<tr class="dataTableHeadingRow"><td class="dataTableHeadingContent">,但对于<td class="dataTableContent">,它只会正确打印该功能中的标签。如何正确打印dataTableContent标签,并将它们保存在循环中? enter image description here

3 个答案:

答案 0 :(得分:1)

查看函数category_list的递归使用,您将在 <tr>内输出<li>个元素。这是invaild HTML。

此外,正文中的每个<tr>只有一个单元格,而标题行中的<tr>有两个单元格。

您应该考虑输出的外观,然后编写代码来解释它,并按照流程查看正在写出的内容。另外,请检查返回到浏览器的实际HTML源代码,而不是浏览器的呈现方式。请注意,不同的浏览器会以不同的方式呈现无效的HTML。

此外,(与您的问题无关)请考虑使用CSS替换borderwidthcellspacingcellpaddingalign HTML属性。另一个考虑因素是使用<head><tbody>元素作为附加语义标记。

进一步说明

你的问题基本上就是这些问题:

    // open the list item
    $list_items[] = '<tr class="dataTableRow">';
    $list_items[] = '<td class="dataTableContent"><li>';

    // construct the category link

    $list_items[] = $cat['categories_name'];

    // recurse into the child list
    $list_items[] = category_list( $cat['categories_id'] );

    // close the list item
    $list_items[] = '</li></td>';
    $list_items[] = '</tr>';

循环的每次迭代都会创建一个新的tr元素!试试这个:

<table border="1" width="100%" cellspacing="0" cellpadding="2">
    <tr class="dataTableHeadingRow">
        <td class="dataTableHeadingContent"><?php echo TABLE_HEADING_PRODUCTS; ?></td>
        <td class="dataTableHeadingContent" align="right"><?php echo TABLE_HEADING_TOTAL_WEIGHT; ?>&nbsp;</td>
    </tr>
    <tr class="dataTableRow">
    <td class="dataTableContent">
<?php
function category_list( $category_parent_id = 0 )
{
    // NOTE THE ADDITIION OF THE PARENT ID:
    $sql  = 'select cd.categories_name,c.categories_id, c.parent_id, c.sort_order from ' . TABLE_CATEGORIES . ' c, ' . TABLE_CATEGORIES_DESCRIPTION . ' cd where c.categories_id = cd.categories_id AND c.parent_id='.$category_parent_id;
    $res  = tep_db_query( $sql );
    $cats = array();

    while ( $cat = tep_db_fetch_array( $res ) )
    {
        $cats[] = $cat;
    }

   if (count($cats) == 0)
   {
      // There are no categories to list
      return '';
   }

    // Create a list HTML string
    $list = '<ul>';

    foreach ( $cats as $cat )
    {
        // open the list item
        $list .= '<li>';

        // construct the category link

        $list .= $cat['categories_name'];

        // recurse into the child list
        $list .= category_list( $cat['categories_id'] );

        // close the list item
        $list .= '</li>';
    }

    // close and return the list
    $list .= '</ul>';
    return $list;

}  

echo category_list();
?>
        </td>
        <td class="dataTableContent"></td>
    </tr>
</table>

请注意,可以对数据和表示逻辑分离进行进一步改进。您不一定需要采用全面的MVC框架;只需使用OOP将SQL查询封装在代表数据库实体的类中。

修改

遵循规范,每个类别都应该在自己的<td>

这需要删除列表元素。 <ul>只能包含<li>元素作为子元素;它不能包含<tr>个孩子。 <td>必须是<tr>的孩子。其他任何地方都不允许这样做。 <tr>只能是<thead><tbody> *或<tfoot>的孩子。这些规则都在HTML DTD中定义。

因此,您需要注意以下几点:

<table border="1" width="100%" cellspacing="0" cellpadding="2">
    <tr class="dataTableHeadingRow">
        <td class="dataTableHeadingContent"><?php echo TABLE_HEADING_PRODUCTS; ?></td>
        <td class="dataTableHeadingContent" align="right"><?php echo TABLE_HEADING_TOTAL_WEIGHT; ?>&nbsp;</td>
    </tr>
<?php
function category_list( $category_parent_id = 0, $level = 0 )
{
    // NOTE THE ADDITIION OF THE PARENT ID:
    $sql  = 'select cd.categories_name,c.categories_id, c.parent_id, c.sort_order from ' . TABLE_CATEGORIES . ' c, ' . TABLE_CATEGORIES_DESCRIPTION . ' cd where c.categories_id = cd.categories_id AND c.parent_id='.$category_parent_id;
    $res  = tep_db_query( $sql );
    $cats = array();

    while ( $cat = tep_db_fetch_array( $res ) )
    {
        $cats[] = $cat;
    }

    $list = '';
    foreach ( $cats as $cat )
    {
        // start the next row:
        $list .= "<tr class=\"dataTableRow\">\n";
        // The cell for the category needs
        $list .= "<td class=\"dataTableContent\">\n";

        // construct the category link.  Note we are now enclosing 
        // this in a div with a left-indent to show the sub level
        // this category is at.  Adjust the padding-left calculation 
        // to suit your page
        $list .= '<div style="padding-left: ' . (2 * $level) . 'em;">';
        $list .= "&bull; {$cat['categories_name']}";
        $list .= "</div>\n";

        // close the row
        $list .= "</td>\n";
        $list .= "<td class=\"dataTableContent\"></td>\n";
        $list .= "</tr>\n";

        // recurse into the child list, incrementing $level
        $list .= category_list( $cat['categories_id'], 1+$level );
    }

    // return the list
    return $list;

}

echo category_list();
?>
</table>

*请注意,<tbody>隐含的元素。它不必在代码中明确定义,但它始终存在于DOM中。

答案 1 :(得分:0)

要遍历数组并将内容显示为表的一部分,我会将您的业务逻辑与显示逻辑分开一点。我的解决方案如下:

<!-- populate the array of data to be displayed -->
<?php $list_items = category_list(); ?>

<!-- start the table, display header rows -->
<table border="1" width="100%" cellspacing="0" cellpadding="2">
<tr class="dataTableHeadingRow">
    <td class="dataTableHeadingContent"><?php echo TABLE_HEADING_PRODUCTS; ?></td>
    <td class="dataTableHeadingContent" align="right"><?php echo TABLE_HEADING_TOTAL_WEIGHT; ?>&nbsp;</td>
</tr>
<tr class="dataTableRow">
<td class="dataTableContent">

<ul>
    <!-- iterate over data array, create ul for each member -->
    <?php 
        foreach($list_items as $item) {
    ?>
        <li><?php print $item ?></li>
    <?php
        }
    ?>
</ul>

<!-- finish the table -->
</td>
</tr>
</table>

<!-- define function which will populate your array -->
<?php
function category_list( $category_parent_id = 0 )
{
    /* 
      this function will look very similar to the one in the 
      one in the original post but will just return the whole
      array instead of printing out one member.
    */

    // populate $items_list...
    return $items_list;
}
?>

请注意我没有测试这个不完整的代码,但这个想法应该是正确的。

答案 2 :(得分:-1)

尝试替换以下代码:

    $list_items[] = '<tr class="dataTableRow">';
    $list_items[] = '<td class="dataTableContent"><li>';

使用:

    $list_items[] = "<tr class='dataTableRow'>";
    $list_items[] = "<td class='dataTableContent'><li>";