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

t3irkdon  于 2021-06-23  发布在  Mysql
关注(0)|答案(3)|浏览(305)

企业中存在着员工与经理的关系 mysql 存储为邻接列表模型employee的表只有一个manager,如果manager的值为空,则表示employee没有manager
关系
员工(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的建议编辑我的问题。
我为解决这个问题而采取的步骤-首先,我改变了邻接列表模型的表结构
到嵌套集模型
从那以后,这门课帮助我达到了预期的效果

vkc1a9a2

vkc1a9a21#

我认为这是一项相当艰巨的任务,因为一个问题是缺乏信息,另一个问题是构建树
无论如何,我尝试了一些应该工作(请仔细研究代码)-我不确定是否有更好的概念,但我认为这是一个好的
创建一个名为 Manageruser_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);
hsgswve4

hsgswve42#

下面是使用动态数据的解决方案

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'];
}
omhiaaxx

omhiaaxx3#

很简单。只需使用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_no 是独一无二的。
也想想 for 6 depth is 0 你说应该倒过来,但你能搞清楚那部分。

相关问题