使用PHP查找子-父(邻接列表模型)关系中子对象的级别或深度

使用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的
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