I have a database with a bunch of categories, some are children:
Array
(
[0] => Array
(
[id] => 1
[name] => Home Improvement
[slug] => Home-Improvement
[parent] =>
[user_id] => 1
[order] => 1
)
[1] => Array
(
[id] => 2
[name] => Asbestos Abatement & Removal
[slug] => Asbestos-Abatement-Removal
[parent] => 1
[user_id] => 1
[order] => 8
)
[2] => Array
(
[id] => 3
[name] => Asphalt & Asphalt Products
[slug] => Asphalt-Asphalt-Products
[parent] => 1
[user_id] => 1
[order] => 9
)
[3] => Array
(
[id] => 4
[name] => Bathroom
[slug] => Bathroom
[parent] => 1
[user_id] => 1
[order] => 10
)
[4] => Array
(
[id] => 5
[name] => Kitchen Cabinets
[slug] => Kitchen-Cabinets
[parent] => 1
[user_id] => 1
[order] => 11
)
[5] => Array
(
[id] => 6
[name] => Ceilings
[slug] => Ceilings
[parent] => 1
[user_id] => 1
[order] => 12
)
[6] => Array
(
[id] => 7
[name] => Cleaning
[slug] => Cleaning
[parent] => 1
[user_id] => 1
[order] => 13
)
[7] => Array
(
[id] => 8
[name] => Closet Organizers & Accessories
[slug] => Closet-Organizers-Accessories
[parent] => 1
[user_id] => 1
[order] => 14
)
[8] => Array
(
[id] => 9
[name] => Concrete
[slug] => Concrete
[parent] => 1
[user_id] => 1
[order] => 15
)
[9] => Array
(
[id] => 10
[name] => Contractors & Service Providers
[slug] => Contractors-Service-Providers
[parent] => 1
[user_id] => 1
[order] => 16
)
What I'm trying to output is something like this:
<ul>
<li>Parent
<ul>
<li>Child</li>
</ul>
</li>
<li>Parent with no Children</li>
</ul>
I'm trying to build a recursive tree script in PHP, but I'm stuck. Here's what I have so far. I'm stuck on what to do between the else: and endif; in the foreach. (And I'm using that syntax just for easier reading here.) Any suggestions?
echo $this->categories->makeTree(0, $this->db->get('categories')->result_array());
public static function makeTree($parent, $array)
{
if (!is_array($array)) return '';
$output = '<ul>';
foreach($array as $key => $value):
if ($value['parent'] == $parent):
$output .= '<li>';
if ($value['parent'] == NULL):
$output .= $value['name'];
else:
endif;
endif;
$output .= '</li>';
endforeach;
$output .= '</ul>';
return $output;
}
EDIT 1
I was able to get this working, although I have a database call in a foreach loop, which probably isn't the best idea:
public function makeTree($parent, $array)
{
if (!is_array($array)) return FALSE;
$output = '<ul>';
foreach($array as $key => $value):
if ($value['parent'] == $parent):
$output .= '<li>';
if ($value['parent'] == NULL):
$output .= $value['name'];
$subcategories = ci()->db->get_where('categories', array('parent' => $value['id']));
if ($subcategories->num_rows() > 0):
$output .= $this->makeTree($value['id'], $subcategories->result_array());
endif;
else:
$output .= $value['name'];
$output .= '</li>';
endif;
endif;
endforeach;
$output .= '</ul>';
return $output;
}
EDIT 2
Here is my final solution, reusing the array instead of doing a DB query:
public function makeTree($parent, $array)
{
if (!is_array($array) OR empty($array)) return FALSE;
$output = '<ul>';
foreach($array as $key => $value):
if ($value['parent'] == $parent):
$output .= '<li>';
if ($value['parent'] == NULL):
$output .= $value['name'];
$matches = array();
foreach($array as $subkey => $subvalue):
if ($subvalue['parent'] == $value['id']):
$matches[$subkey] = $subvalue;
endif;
endforeach;
$output .= $this->makeTree($value['id'], $matches);
else:
$output .= $value['name'];
$output .= '</li>';
endif;
endif;
endforeach;
$output .= '</ul>';
return $output;
}
Though this seems answered, have a look here. With the shown function you can convert your flat data to nested data with only one iteration. Creating an ul-list from that nested data is then very easy. For example:
function nested2ul($data) {
$result = array();
if (sizeof($data) > 0) {
$result[] = '<ul>';
foreach ($data as $entry) {
$result[] = sprintf(
'<li>%s %s</li>',
$entry['name'],
nested2ul($entry['children'])
);
}
$result[] = '</ul>';
}
return implode($result);
}
echo nested2ul(array(flat2nested( $yourFlatData ));
The good thing about this approach is that you don't have to re-iterate again and again over the input data just to find the child-elements.
Here is my final solution, reusing the array instead of doing a DB query. If you do have a better solution, please post!
public function makeTree($parent, $array)
{
if (!is_array($array) OR empty($array)) return FALSE;
$output = '<ul>';
foreach($array as $key => $value):
if ($value['parent'] == $parent):
$output .= '<li>';
if ($value['parent'] == NULL):
$output .= $value['name'];
$matches = array();
foreach($array as $subkey => $subvalue):
if ($subvalue['parent'] == $value['id']):
$matches[$subkey] = $subvalue;
endif;
endforeach;
$output .= $this->makeTree($value['id'], $matches);
else:
$output .= $value['name'];
$output .= '</li>';
endif;
endif;
endforeach;
$output .= '</ul>';
return $output;
}
I usualy use something like this, please note
1st this piece of code is using deprecated mysql_*
2nd you should have one database field named level, if NULL it is the main category, if it has a number, it is a subcategory of the category with that number as id
function getFamilies($level = 0) {
$level++;
$sql = "SELECT id from families WHERE level IS NULL";
if (mysql_num_rows($result) > 0) {
echo "<ul>";
while($row = mysql_fetch_assoc($result)) {
echo "<li>".$row['id'];
getSubFamilies($level, $row['id']);
echo "</li>";
}
echo "</ul>";
}
}
function getSubFamilies($level, $id) {
$level++;
$sqlSubFamilies = "SELECT id FROM families WHERE level = ".$id."";
$resultSubFamilies = mysql_query($sqlSubFamilies);
if (mysql_num_rows($resultSubFamilies) > 0) {
echo = "<ul>";
while($rowSubFamilies = mysql_fetch_assoc($resultSubFamilies)) {
echo "<li>".$rowSubFamilies['id'];
getSubFamilies($level, $rowSubFamilies['id']);
echo "</li>";
}
echo "</ul>";
}
}
getFamilies($level = 0);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With