我使用codeigniter和有一个表3列(id,名称,parent_id)。一个类别可以有多个子类别,一个子类别可以有多个子类别。
我一直在尝试使用以下代码获取所有类别及其子类别:
public function getCategory($id)
{
$categories = array();
while($id != 0)
{
$this->db->from('categories'); //$this->table is a field with the table of categoris
$this->db->where('id', $id);
$this->db->limit(1);
$result = $this->db->get()->row(); //fetching the result
$categories[] = $result;
$id = $result->parent_id;
}
return $categories;
}
public function getAllCategories()
{
$this->db->select('id');
$this->db->from('categories'); //$this->table is a field with the table of categoris
$this->db->where('parent_id', 0);
$mainCategories = $this->db->get()->result(); //fetching the result
$result = array();
foreach($mainCategories as $id)
{
$result[] = $this->getCategory($id->id);
}
return $result;
}
但它只返回1级类别。
我的问题是如何完成我的任务:获得每个级别的所有类别和子类别。
这是一个codeigniter库,我在stackoverflow的答案中找到了它,但我不记得它的所有者。我对它做了一些修改,将嵌套的类别作为列表返回。它对我很有效。
<?php
if (!defined('BASEPATH'))
exit('No direct script access allowed');
class Tree {
var $table = '';
var $CI = '';
var $ul_class = '';
var $iteration_number = 0;
function Tree($config = array()) {
$this -> table = $config['table'];
$this -> CI = &get_instance();
$this -> CI -> load -> database();
$this -> ul_class = $config['ul_class'];
}
function getTree($parent_id = 1) {
$this -> iteration_number++;
$this -> CI -> db -> where('parent_id', $parent_id);
$first_level = $this -> CI -> db -> get($this -> table) -> result();
if($this->iteration_number == 1)
$tree = '<ul id="red" class="' . $this -> ul_class . '">';
else
$tree = '<ul>';
foreach ($first_level as $fl) {
$this -> CI -> db -> where('parent_id', $fl -> category_id);
$count = $this -> CI -> db -> count_all_results($this -> table);
if ($count != 0) {
$tree .= '<li><span>' . $fl -> category_name . '</span>';
$tree .= $this -> getTree($fl -> category_id);
} else {
$tree .= '<li><a href="'.base_url().'categories/sub/'.str_replace(' ', '-', $fl -> category_name).'" cat_id="'.$fl -> category_id.'" class="leaf">' . $fl -> category_name . '</a>';
}
$tree .= '</li>';
}
$tree .= '</ul>';
return $tree;
}
}
?>
您可以从控制器中使用它,如下所示:
$config['ul_class']='treeview';
$config['table']='categories';
$this->load->library('tree',$config);
$tree = $this->tree->getTree();
DB表的结构如下所示:
CREATE TABLE IF NOT EXISTS `categories` (
`category_id` int(4) NOT NULL AUTO_INCREMENT,
`category_name` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
`category_description` varchar(500) COLLATE utf8_unicode_ci NOT NULL,
`parent_id` int(4) NOT NULL,
PRIMARY KEY (`category_id`),
KEY `categories_categories_fk_idx` (`parent_id`)
) ENGINE=InnoDB
您可以通过库中的getTree函数修改返回的结果,以返回所需的内容。
解决问题的最简单方法是添加递归。
public function getCategoryTreeForParentId($parent_id = 0) {
$categories = array();
$this->db->from('categories');
$this->db->where('parent_id', $parent_id);
$result = $this->db->get()->result();
foreach ($result as $mainCategory) {
$category = array();
$category['id'] = $mainCategory->id;
$category['name'] = $mainCategory->name;
$category['parent_id'] = $mainCategory->parent_id;
$category['sub_categories'] = $this->getCategoryTreeForParentId($category['id']);
$categories[$mainCategory->id] = $category;
}
return $categories;
}
通过预加载所有类别并对数组进行操作,从而跳过对每个新父id的查询,可以大大提高这种方法的速度。
我也没有使用codeigniter的对象,因为我不知道他们。如果它们支持魔法setters/getters,或者可以被说服接受一个子对象数组,它们应该被用来代替我在这里构建的数组。
该算法所做的是:加载具有给定父类id的所有类别,循环遍历所有这些类别,假设迭代类别id为父类id,并为其加载所有内容。这将有效地加载所有类别,只要它们引用现有类别。
这其中有一个小小的危险:当你构建了类别a和类别B,其中a以B为父,B以a为父,你将陷入一个无休止的循环,因为它们一次又一次地相互加载。这迫使您在数据中有一个干净的树结构。
使现代化
由于这仍然得到支持:关于这个实现还有另一个建议。如果类别树较大或具有多个级别,则可能会遇到性能问题,因为此实现会使用新的查询参数一次又一次地加载类别。这很容易导致数十个、数百个或数千个查询,具体取决于您的类别树。
一种更有效的方法是从category表中加载所有类别(使用一个查询),并在应用程序中使用递归对它们进行排序。这是少数情况之一,早期评估确实可以提高绩效。
如果在同一个请求中多次需要该树,甚至可以通过静态变量添加缓存(缓存的所有常见危险)。
问题内容: 这是我想要做的事情:-我需要一个函数,当将其作为参数传递时,ID(用于事物类别)将提供所有子类别,子子类别和子子子..etc 。-我在考虑使用递归函数,因为我不知道子类别及其子类别的数量,依此类推,这是到目前为止我一直在尝试的操作 如果我使用return而不是echo,我将不会得到相同的结果。我需要一些帮助以解决此问题或从头开始重写它 问题答案: 我很难弄清楚你的职能。我认为这会做您想
问题内容: 如何获得所选公司中所有员工的平均工资?我首先选择公司,然后传递ID,然后基于该ID,我将所有员工都带到那里并将其信息显示在表格中。目标是获得该组中每个人的平均工资。 问题答案: 您可以将薪金加起来,然后除以雇员数: 话虽如此,我敦促您在走那条路之前重新考虑。如果JSP内的代码超过1-2页,将严重阻碍您对其进行维护的机会。您的所有业务逻辑都应在代码中(例如,在Servlet中)发生,并且
有一个类别,具有以下(重要)属性: 我正在尝试实现类别/子类别的概念。一个类别可以有零个或多个子类别。一个类别只能有一个父类别(可以为null)。对于顶级类别,parentCategory=null。 现在,我有一个所有类别的列表,
问题内容: 可以说我有一个Java程序包,其中包含所有继承自的类,我能以某种方式获得所有这些类吗?我正在锁定以下方面的东西: 这样有可能吗? 问题答案: 这是一个基本示例,假定类未打包JAR:
我想在前端获得所有woocommerce类别的子类别,结果如下: 这是我所拥有的(但不是我想要的): 这段代码显示了类别和子类别,但是子类别不在应该在的地方,子类别就像这样的单独链接:
我对数据库非常陌生,我想知道原始sql查询。我有两个表Category和Product,Product表有一个foreign_key(Category_id)。 如何获得每个类别有10个产品的所有类别?所以我将在第一页显示每个类别名称和10个产品。 并且还想查询该产品的评论表。如何连接两个表(类别和产品(1),评论(2)