1

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

<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 标签,并将它们都保持在循环中? 在此处输入图像描述

4

3 回答 3

1

查看您对函数的递归使用,category_list您将s中输出<tr>元素。这是无效的 HTML。 <li>

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

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

此外,(与您的问题无关)考虑用 CSS 替换borderwidthcellspacing和HTML 属性。另一个考虑是使用and元素作为附加的语义标记。cellpaddingalign<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>.

这需要删除列表元素。A<ul>只能包含<li>子元素;它不能包含<tr>孩子。A<td>必须是 a 的子级<tr>。其他任何地方都不允许这样做。A<tr>只能是 a <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 中。

于 2012-09-26T14:30:55.613 回答
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;
}
?>

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

于 2012-09-26T14:31:35.570 回答
-1

尝试替换以下代码:

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

和:

    $list_items[] = "<tr class='dataTableRow'>";
    $list_items[] = "<td class='dataTableContent'><li>";
于 2012-09-26T14:52:01.340 回答