В таблице 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.
Шаг, предпринятый мной для решения проблемы - сначала я изменил структуру своей таблицы с Модель списка смежности
кому: Модель вложенного множества
после этого этот класс помог мне добиться желаемого результата
почему 11 должно быть глубиной 3? - не должно быть 11 в столбце сотрудников и связано с менеджером? (по вашему примеру ...)
да, я тоже этого не понял. решил, что корреляции нет, и что он просто опубликовал это для хихиканья
@sintakonte - потому что, есть 3 сотрудника под менеджером 11 (10, 15, 9). а 11 родителей будут нулевыми.
@sintakpnte - проверьте это) stackoverflow.com/questions/10688608/…
а что 6? 6 сотрудник без менеджера что ли? если да, то почему это даже в вашей таблице?
И следующий вопрос: может ли любой сотрудник иметь более одного менеджера и наоборот? если да, то что произойдет, если 15 - менеджер 10 или 9 - менеджер 11 и т. д., я имею в виду, чувак, ты должен придумать здесь немного больше данных, потому что это очень паршивое описание вопроса;)
мой ответ тебе помог?
@sintakonte, спасибо за решение. Я считаю, что логики достаточно, но в таблице есть большие данные. Отображается ошибка «Неустранимая ошибка: достигнут максимальный уровень вложенности функции« 256 », прерывание!»
Простой. Просто используйте оператор 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, если case не существует или если запрос не возвращает строк. Я также предполагаю, что manager_no
уникален.
Также подумайте, что for 6 depth is 0
, по вашему мнению, должен быть перевернут, но вы можете понять эту часть.
Я хочу работать с динамическими данными с помощью функции - @Alex
не знаю, что это значит
Данные хранятся Модель смежности в моем примере, почему вы используете случай переключения
Вот решение для динамических данных
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_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);
Используете переключатель? php.net/manual/en/control-structures.switch.php