我有一个数据库查询,它为我提供了一些员工数据的输出.我想使用此数据传递给生成组织结构图的插件.我正在提取的JSON对象中有一些字段是:
FirstName
LastName
EmployeeID
ManagerEmployeeID
Manager Name
Run Code Online (Sandbox Code Playgroud)
数据作为扁平JSON对象返回,在层次结构中员工及其经理之间没有嵌套或关联.
由于我无法更改源数据(数据库查询)的输出,我试图找出一种嵌套数据的方法,以便JSON输出成为嵌套输出.
我的目标是获取此数组并基于ManagerID和EmployeeID将其嵌套,以便我可以创建树层次结构.
示例数据:
• Tom Jones
o Alice Wong
o Tommy J.
• Billy Bob
o Rik A.
? Bob Small
? Small Jones
o Eric C.
Run Code Online (Sandbox Code Playgroud)
我的平面数据示例:
{
"FirstName": "Tom"
"LastName": "Jones"
"EmployeeID": "123"
"ManagerEmployeeID": ""
"Manager Name": ""
},
{
"FirstName": "Alice"
"LastName": "Wong"
"EmployeeID": "456"
"ManagerEmployeeID": "123"
"Manager Name": "Tom Jones"
},
{
"FirstName": "Tommy"
"LastName": "J."
"EmployeeID": "654"
"ManagerEmployeeID": "123"
"Manager Name": "Tom Jones"
},
{
"FirstName": "Billy"
"LastName": "Bob"
"EmployeeID": "777"
"ManagerEmployeeID": ""
"Manager Name": ""
},
{
"FirstName": "Rik"
"LastName": "A."
"EmployeeID": "622"
"ManagerEmployeeID": "777"
"Manager Name": "Billy Bob"
},
{
"FirstName": "Bob"
"LastName": "Small"
"EmployeeID": "111"
"ManagerEmployeeID": "622"
"Manager Name": "Rik A."
},
{
"FirstName": "Small"
"LastName": "Jones"
"EmployeeID": "098"
"ManagerEmployeeID": "622"
"Manager Name": "Rik A"
},
{
"FirstName": "Eric"
"LastName": "C."
"EmployeeID": "222"
"ManagerEmployeeID": "777"
"Manager Name": "Billy Bob"
}
Run Code Online (Sandbox Code Playgroud)
示例所需输出:
[
{
"FirstName": "Tom",
"LastName": "Jones",
"EmployeeID": "123",
"ManagerEmployeeID": "",
"Manager Name": "",
"employees": [
{
"FirstName": "Alice",
"LastName": "Wong",
"EmployeeID": "456",
"ManagerEmployeeID": "123",
"Manager Name": "Tom Jones"
},
{
"FirstName": "Tommy",
"LastName": "J.",
"EmployeeID": "654",
"ManagerEmployeeID": "123",
"Manager Name": "Tom Jones"
}
]
},
{
"FirstName": "Billy",
"LastName": "Bob",
"EmployeeID": "777",
"ManagerEmployeeID": "",
"Manager Name": "",
"employees": [
{
"FirstName": "Rik",
"LastName": "A.",
"EmployeeID": "622",
"ManagerEmployeeID": "777",
"Manager Name": "Billy Bob",
"employees": [
{
"FirstName": "Bob",
"LastName": "Small",
"EmployeeID": "111",
"ManagerEmployeeID": "622",
"Manager Name": "Rik A."
},
{
"FirstName": "Small",
"LastName": "Jones",
"EmployeeID": "098",
"ManagerEmployeeID": "622",
"Manager Name": "Rik A"
}
]
},
{
"FirstName": "Eric",
"LastName": "C.",
"EmployeeID": "222",
"ManagerEmployeeID": "777",
"Manager Name": "Billy Bob"
}
]
}
]
Run Code Online (Sandbox Code Playgroud)
基本上我试图使用EmployeeID和ManagerEmployeeID作为两者之间的链接从平面对象创建嵌套的JSON输出.
用PHP解决这类问题的最佳方法是什么?
赏金更新:
以下是该问题的测试用例:https://eval.in/private/4b0635c6e7b059
您将看到名称中的最后一条记录Issue Here未显示在结果集中.它有一个managerID匹配根节点,应该在"Tom Jones" employees数组中.
我有以下实用程序类来完全按照您的需要进行操作.
class NestingUtil
{
/**
* Nesting an array of records using a parent and id property to match and create a valid Tree
*
* Convert this:
* [
* 'id' => 1,
* 'parent'=> null
* ],
* [
* 'id' => 2,
* 'parent'=> 1
* ]
*
* Into this:
* [
* 'id' => 1,
* 'parent'=> null
* 'children' => [
* 'id' => 2
* 'parent' => 1,
* 'children' => []
* ]
* ]
*
* @param array $records array of records to apply the nesting
* @param string $recordPropId property to read the current record_id, e.g. 'id'
* @param string $parentPropId property to read the related parent_id, e.g. 'parent_id'
* @param string $childWrapper name of the property to place children, e.g. 'children'
* @param string $parentId optional filter to filter by parent
*
* @return array
*/
public static function nest(&$records, $recordPropId = 'id', $parentPropId = 'parent_id', $childWrapper = 'children', $parentId = null)
{
$nestedRecords = [];
foreach ($records as $index => $children) {
if (isset($children[$parentPropId]) && $children[$parentPropId] == $parentId) {
unset($records[$index]);
$children[$childWrapper] = self::nest($records, $recordPropId, $parentPropId, $childWrapper, $children[$recordPropId]);
$nestedRecords[] = $children;
}
}
return $nestedRecords;
}
}
Run Code Online (Sandbox Code Playgroud)
使用您的代码:
$employees = json_decode($flat_employees_json, true);
$managers = NestingUtil::nest($employees, 'EmployeeID', 'ManagerEmployeeID', 'employees');
print_r(json_encode($managers));
Run Code Online (Sandbox Code Playgroud)
输出:
[
{
"FirstName": "Tom",
"LastName": "Jones",
"EmployeeID": "123",
"ManagerEmployeeID": "",
"Manager Name": "",
"employees": [
{
"FirstName": "Alice",
"LastName": "Wong",
"EmployeeID": "456",
"ManagerEmployeeID": "123",
"Manager Name": "Tom Jones",
"employees": []
},
{
"FirstName": "Tommy",
"LastName": "J.",
"EmployeeID": "654",
"ManagerEmployeeID": "123",
"Manager Name": "Tom Jones",
"employees": []
}
]
},
{
"FirstName": "Billy",
"LastName": "Bob",
"EmployeeID": "777",
"ManagerEmployeeID": "",
"Manager Name": "",
"employees": [
{
"FirstName": "Rik",
"LastName": "A.",
"EmployeeID": "622",
"ManagerEmployeeID": "777",
"Manager Name": "Billy Bob",
"employees": [
{
"FirstName": "Bob",
"LastName": "Small",
"EmployeeID": "111",
"ManagerEmployeeID": "622",
"Manager Name": "Rik A.",
"employees": []
},
{
"FirstName": "Small",
"LastName": "Jones",
"EmployeeID": "098",
"ManagerEmployeeID": "622",
"Manager Name": "Rik A",
"employees": []
}
]
},
{
"FirstName": "Eric",
"LastName": "C.",
"EmployeeID": "222",
"ManagerEmployeeID": "777",
"Manager Name": "Billy Bob",
"employees": []
}
]
}
]
Run Code Online (Sandbox Code Playgroud)
Edit1:修复以避免忽略某些员工
如果最后一项是具有有效经理的员工但经理不在列表中,则会被忽略,因为应该位于哪里?,它不是根,但没有有效的经理.
为避免这种情况,请在实用程序中的return语句之前添加以下行.
if (!$parentId) {
//merge residual records with the nested array
$nestedRecords = array_merge($nestedRecords, $records);
}
return $nestedRecords;
Run Code Online (Sandbox Code Playgroud)
Edit2:将实用程序更新为PHP5.6
在PHP7中进行了一些测试后,该实用程序在php7.0中工作正常但在php5.6中没有,我不知道为什么,但是在数组引用和未设置中.我更新实用程序代码以使用php5.6和您的用例.
public static function nest($records, $recordPropId = 'id', $parentPropId = 'parent_id', $childWrapper = 'children', $parentId = null)
{
$nestedRecords = [];
foreach ($records as $index => $children) {
if (isset($children[$parentPropId]) && $children[$parentPropId] == $parentId) {
$children[$childWrapper] = self::nest($records, $recordPropId, $parentPropId, $childWrapper, $children[$recordPropId]);
$nestedRecords[] = $children;
}
}
if (!$parentId) {
$employeesIds = array_column($records, $recordPropId);
$managers = array_column($records, $parentPropId);
$missingManagerIds = array_filter(array_diff($managers, $employeesIds));
foreach ($records as $record) {
if (in_array($record[$parentPropId], $missingManagerIds)) {
$nestedRecords[] = $record;
}
}
}
return $nestedRecords;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1289 次 |
| 最近记录: |