使用PHP查找子-父(邻接列表模型)关系中子对象的级别或深度
mysql的使用PHP查找子-父(邻接列表模型)关系中子对象的级别或深度,php,mysql,codeigniter,Php,Mysql,Codeigniter,mysql的mysql表中有一个员工和经理的关系,该关系存储为邻接列表模型。如果manager的值为空,则employee只有一个经理,而manager有多个员工,这意味着employee没有经理 关系 员工(1对1)经理 员工(多对一)经理 employee manager 10 11 15 10 9 15 6 0 我想成为一名有深度的经理 11 depth
mysql
表中有一个员工和经理的关系,该关系存储为邻接列表模型。如果manager的值为空,则employee只有一个经理,而manager有多个员工,这意味着employee没有经理
关系
员工(1对1)经理员工(多对一)经理
employee manager
10 11
15 10
9 15
6 0
我想成为一名有深度的经理
11 depth is 3
for 10 depth is 2
for 15 depth is 1
for 6 depth is 0
......
......
.......
如何使用php实现这一点,下面是我不完整的逻辑
<?php
get_level(11) // 3
get_level(10) // 2
get_level(15) // 1
get_level(6) // 0
function get_level($level){
$this->db->get_where('manager_user', array('manager_no' => $level))
->result_array()
// logic
return no; //3 for 11
}
?>
有人能帮我吗。如果有人向我提供具有mysql功能的解决方案,这也将有助于我存储在mysql多级层次结构中的数据
编辑:我按照@sintakonte的建议编辑我的问题
我为解决这个问题而采取的步骤-首先,我将表结构从
到
在那之后,我得到了想要的结果,这很简单。只需使用switch语句:
function get_level($level){
$query = $this->db->get_where('manager_user', array('manager_no' => $level));
if ($query->num_rows !== 1) {
return false;
}
$manager_no = intval($query->row()->manager_no);
switch ($manager_no) {
default:
return false;
case 11:
return 3;
case 10:
return 2;
case 15
return 1;
case 6:
return 0;
}
}
如果大小写不存在或查询不返回行,则返回false。我还假设manager\u no
是唯一的
也可以认为6的
深度为0
你说的应该颠倒过来,但你可以找出那一部分。下面是使用动态数据的解决方案
function get_level($level){
$query = $this->db->query('SELECT count(*) as depth FROM manager_user WHERE manager_no > (SELECT manager_no FROM roles WHERE manager_no ='.$level.')');
$depth = $query->row_array()['depth'];
}
我认为这是一项相当艰巨的任务,因为一个问题是缺乏信息,另一个问题是构建树 无论如何,我尝试了一些应该有效的方法(请仔细研究代码)-我不确定是否有更好的概念,但我认为这是一个好的概念 创建一个名为
Manageruser\u model.php的模型,如下所示
class Manageruser_model extends CI_Model
{
private $arrFieldsWithKeys = [];
private function createTree()
{
$arrResult = $this->db->get_where('manager_user')->result();
//in case a manager is no employee - we've to add this one as an employee with manager id 0
$arrResult = $this->addManagersAsEmployee($arrResult);
$arrFieldsWithKeys = [];
foreach($arrResult AS $obj)
{
$arrFieldsWithKeys[$obj->employee] = $obj;
if (!isset($arrFieldsWithKeys[$obj->manager]) && $obj->manager != 0) $arrFieldsWithKeys[$obj->manager] = $obj;
}
$arrFoundChilds = [];
foreach($arrResult AS $obj)
{
if (isset($arrFieldsWithKeys[$obj->manager]))
{
if (!isset($arrFieldsWithKeys[$obj->manager]->childs)) $arrFieldsWithKeys[$obj->manager]->childs = [];
$arrFieldsWithKeys[$obj->manager]->childs[] = $obj;
$arrFoundChilds[] = $obj->employee;
}
}
$this->arrFieldsWithKeys = $arrFieldsWithKeys;
$arrRemovedChildsFromMasterNode =array_diff_key($arrFieldsWithKeys,array_flip($arrFoundChilds));
$this->setTreeDepth($arrRemovedChildsFromMasterNode);
}
private function addManagersAsEmployee($arrResult)
{
$employees = array_column($arrResult, 'employee');
$manager = array_column($arrResult, 'manager');
$arrMissingManagersAsEmployee = array_diff($manager, $employees);
foreach($arrMissingManagersAsEmployee AS $strId)
{
if ($strId > 0)
{
$obj = new stdClass();
$obj->employee = $strId;
$obj->manager = 0;
$arrResult[] = $obj;
}
}
return $arrResult;
}
private function setTreeDepth($arr)
{
$level = 0;
foreach($arr AS $obj)
{
if (isset($obj->childs))
{
$level = $this->setTreeDepth($obj->childs);
$obj->level = $level;
}
else
{
$obj->level = 0;
}
}
return $level + 1;
}
public function getDepth(int $id)
{
if (empty($this->arrFieldsWithKeys)) $this->createTree();
if (!isset($this->arrFieldsWithKeys[$id])) throw new Exception($id.' doesn\'t exist.');
return $this->arrFieldsWithKeys[$id]->level;
}
}
现在在你的控制器中,你可以简单地加载模型,得到一个深度,就像
$this->load->model('Manageruser_model');
echo $this->Manageruser_model->getDepth(11);
使用开关?为什么11应该是深度3员工栏中的11不应该也是与经理关联的吗?(根据你的例子…)是的,我也不明白。我想这两者之间没有关联,他只是为了giggles@sintakonte-因为经理手下有3名员工11(10、15、9)。和11 parent将为零。@sintakpnte-请检查此项)我想使用函数操作动态数据-@alex不知道这意味着什么数据存储在我的示例中为什么使用switch case