I have a table showing the list of categories and subcategories, using a function to loop through the parent/child tree. Here is the markup of the script:
<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; ?> </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>
At the moment this currently prints the <tr class="dataTableHeadingRow"> and both the <td class="dataTableHeadingContent">correctly, but for the <td class="dataTableContent">, it is only printing the tag in the function correctly. How would I print both the dataTableContent tags correctly, and keep them both in the loop?

Looking at your recursive use of the function
category_listyou will be outputting<tr>elements inside<li>s. This is invaild HTML.Also, each
<tr>in the body will only have one cell, whereas the<tr>in the header row has two cells.You should consider how the output should look, then write your code to account for that, and follow the flow through to see what is being written out. Also, check the actual HTML source returned to your browser, not how your browser renders it. Note that different browsers will render invalid HTML differently.
Also, (not related to your problem) consider replacing the
border,width,cellspacing,cellpaddingandalignHTML attributes with CSS instead. Another consideration would be to use the<head>and<tbody>elements as additional semantic markup.Further Explanation
Your problem is essentially these lines:
Every iteration of your loop is creating a new
trelement! Try this instead:Note that further improvements can be made regarding data and presentation logic separation. You don’t necessarily need to adopt a full-scale MVC framework; just use OOP to encapsulate your SQL queries within classes which represent your database entities.
EDIT
Following the specification that each category should be in its own
<td>.This requires the removal of the list elements. A
<ul>can only contain<li>elements as children; it cannot contain<tr>children. A<td>MUST be a child of a<tr>. It is not allowed anywhere else. A<tr>can only be a child of a<thead>,<tbody>* or<tfoot>. These rules are all defined in the HTML DTD.Therefore, the following is the sort of thing you need to be looking at:
*Note that
<tbody>is an implied element. It doesn’t have to be explicitly defined in the code, but it will always be there in the DOM.