Я хотел бы написать рекурсивную функцию PHP для извлечения всех дочерних элементов для указанной категории. Я попробовал описанный здесь, но он не выводил то, что я ожидал.
Таблица моих категорий выглядит так:
CREATE TABLE `categories` ( `category_id` smallint(5) unsigned NOT NULL AUTO_INCREMENT, `category_name` varchar(256) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, `category_slug` varchar(256) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, `category_parent` smallint(5) unsigned NOT NULL DEFAULT '0', `category_description_ro` text CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, `category_description_en` text CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, PRIMARY KEY (`category_id`) ) ENGINE=MyISAM AUTO_INCREMENT=8 DEFAULT CHARSET=latin1
Ниже приведен пример данных таблицы:
category id | category name | category_parent 1 Categoria 1 0 2 Categoria 2 0 3 Categoria 3 0 4 Categoria 1.1 1 5 Categoria 1.2 1 6 Categoria 1.3 1 7 Categoria 1.1.2 4
Благодарю.
function get_categories($parent = 0) { $html = '<ul>'; $query = mysql_query("SELECT * FROM `categories` WHERE `category_parent` = '$parent'"); while($row = mysql_fetch_assoc($query)) { $current_id = $row['category_id']; $html .= '<li>' . $row['category_name']; $has_sub = NULL; $has_sub = mysql_num_rows(mysql_query("SELECT COUNT(`category_parent`) FROM `categories` WHERE `category_parent` = '$current_id'")); if($has_sub) { $html .= get_categories($current_id); } $html .= '</li>'; } $html .= '</ul>'; return $html; } print get_categories();
Вот что я использую для отображения вложенных ссылок, это только делает один запрос БД, а затем кэширует результаты в полезном массиве.
function generate_menu($parent, $menu_array=Array(), $level = 0, $first=0) { $has_childs = false; if (empty($menu_array)) { $rs = mysql_query("SELECT id, parent, name FROM cats"); while ( $row = mysql_fetch_assoc($rs) ) { $menu_array[$row['id']] = array('name' => $row['name'],'parent' => $row['parent']); } } foreach ($menu_array as $key => $value) { if ($value['parent'] == $parent) { //if this is the first child print '<ul>' if ($has_childs === false) { //don't print '<ul>' multiple times $has_childs = true; if ($first == 0){ echo "<ul id=\"nav\">\n"; $first = 1; } else { echo "\n<ul>\n"; } } $pad = str_repeat('– ', $level); echo "<li><a href=\"http://" . $value['url'].'/\">' . $value['name'] . "</a>"; generate_menu($key, $menu_array, $level + 1, $first); //call function again to generate nested list for subcategories belonging to this category echo "</li>\n"; } } if ($has_childs === true) echo "</ul>\n"; }
Я нашел довольно простой пример, который работает над массивом категорий, полученных из БД. Запрос «SELECT * FROM categories» создаст массив всех категорий.
В моей таблице категорий у меня есть поля «id», «parent_id» и «name». Это все. Базовые категории имеют родительский идентификатор, заданный как 0. Подкоды имеют parent_id, заданные как идентификатор родительской категории. Просто так? Вот код:
$categories = [ ['id'=>1,'parentID'=>0, 'name' => 'Main 1' ], ['id'=>2,'parentID'=>0, 'name' => 'Main 2' ], ['id'=>3,'parentID'=>0, 'name' => 'Main 3' ], ['id'=>4,'parentID'=>0, 'name' => 'Main 4' ], ['id'=>5,'parentID'=>1, 'name' => 'sub 1 - 1' ], ['id'=>6,'parentID'=>1, 'name' => 'sub 1 - 2' ], ['id'=>11,'parentID'=>5, 'name' => 'sub 1 - 2' ], ['id'=>12,'parentID'=>5, 'name' => 'sub 1 - 2' ], ['id'=>13,'parentID'=>5, 'name' => 'sub 1 - 2' ], ['id'=>14,'parentID'=>6, 'name' => 'sub 1 - 2' ], ['id'=>7,'parentID'=>2, 'name' => 'sub 2 - 1' ], ['id'=>8,'parentID'=>2, 'name' => 'sub 2 - 2' ], ['id'=>9,'parentID'=>3, 'name' => 'sub 3 - 1' ], ['id'=>10,'parentID'=>3, 'name' => 'sub 3 - 2' ] ]; function getCategories($categories, $parent = 0) { $html = "<ul>"; foreach($categories as $cat) { if($cat['parentID'] == $parent) { $current_id = $cat['id']; $html .= "<li>" . $cat['name'] ; $html .= getCategories($categories, $current_id); $html .= "</li>"; } } $html .= "</ul>"; return $html; } echo getCategories($categories) ;
$ categories – это эффект одного запроса sql "SELECT * FROM categories"