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

时间:2018-08-09 06:34:42

标签: php mysql codeigniter

mysql表中存在员工与经理的关系,该关系存储为邻接表模型员工只有一个经理,并且如果经理的值为空,则经理有很多员工,这意味着没有经理的员工

关系

员工(1对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的建议编辑问题。

我已采取步骤解决此问题-首先,我从The Adjacency List Model更改了表结构

The Nested Set Model

之后this class帮助我达到了预期的效果

3 个答案:

答案 0 :(得分:0)

简单。只需使用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应该颠倒过来,但是您可以弄清楚那一部分。

答案 1 :(得分: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'];
}

答案 2 :(得分:0)

我认为这是一项艰巨的任务-因为一个问题是缺乏信息,另一个问题是建造树

无论如何,我尝试了一些可行的方法(请仔细研究代码)-我不确定是否存在更好的概念,但我认为这是一个好主意

创建一个名为combined.filter(like='el') 的模型,如下所示:

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;
    }
}