Php I';我在通过引用使用递归函数修改数组时遇到问题
需要一些数组引用专家的帮助。有一天我的头撞到了墙上。我需要将一系列路径转换为数据/子结构。我有来自MySQL的这些记录Php I';我在通过引用使用递归函数修改数组时遇到问题,php,arrays,Php,Arrays,需要一些数组引用专家的帮助。有一天我的头撞到了墙上。我需要将一系列路径转换为数据/子结构。我有来自MySQL的这些记录 +----+---------------------------------+------------------------------------------------------------------------+ | id | folder | path_string
+----+---------------------------------+------------------------------------------------------------------------+
| id | folder | path_string |
+----+---------------------------------+------------------------------------------------------------------------+
| 1 | installfolder | INSTALLATION PARTNERS |
| 2 | installCOIfolder | INSTALLATION PARTNERS/DOCUMENTS/COI |
| 3 | installDeliveryTicketsfolder | INSTALLATION PARTNERS/DOCUMENTS/DELIVERY TICKETS |
| 4 | installPdfPackagefolder | INSTALLATION PARTNERS/PDF INSTALLATION PACKAGE |
| 5 | installPunchListfolder | INSTALLATION PARTNERS/PDF INSTALLATION PACKAGE/PDF PUNCHLIST FLOORPLAN |
| 6 | installSitePhotosfolder | INSTALLATION PARTNERS/SITE PHOTOS |
| 7 | installChangeOrdersfolder | INSTALLATION PARTNERS/DOCUMENTS/CHANGE ORDERS |
| 8 | installCompletionfolder | INSTALLATION PARTNERS/SITE PHOTOS/COMPLETION |
| 9 | installDamagesandWarrantyfolder | INSTALLATION PARTNERS/SITE PHOTOS/DAMAGES & WARRANTY |
| 10 | installMarketingfolder | INSTALLATION PARTNERS/SITE PHOTOS/MARKETING |
| 11 | installProgressfolder | INSTALLATION PARTNERS/SITE PHOTOS/MARKETING |
| 12 | meadowsfolder | MEADOWS PROJECT DOCUMENTS |
| 13 | meadowsChangeOrdersfolder | MEADOWS PROJECT DOCUMENTS/CHANGE ORDERS |
| 14 | meadowsPunchListfolder | MEADOWS PROJECT DOCUMENTS/PUNCHLIST |
| 15 | meadowsPunchListItemsfolder | MEADOWS PROJECT DOCUMENTS/PUNCHLIST ITEMS |
+----+---------------------------------+------------------------------------------------------------------------+
DROP TABLE IF EXISTS `validation_paths`;
CREATE TABLE `validation_paths` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`folder` varchar(100) NOT NULL,
`path_string` varchar(400) DEFAULT NULL,
`box_id_referer` varchar(100) DEFAULT NULL,
`title` varchar(100) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `validation_paths` (`id`, `folder`, `path_string`, `box_id_referer`, `title`) VALUES
(1, 'installfolder', 'INSTALLATION PARTNERS', '', 'Installation Folder'),
(2, 'installCOIfolder', 'INSTALLATION PARTNERS/DOCUMENTS/COI', '', 'COI Folder'),
(3, 'installDeliveryTicketsfolder', 'INSTALLATION PARTNERS/DOCUMENTS/DELIVERY TICKETS', '', 'Delivery Tickets'),
(4, 'installPdfPackagefolder', 'INSTALLATION PARTNERS/PDF INSTALLATION PACKAGE', '', 'PDF Installation Packages'),
(5, 'installPunchListfolder', 'INSTALLATION PARTNERS/PDF INSTALLATION PACKAGE/PDF PUNCHLIST FLOORPLAN', '', 'PDF Floorplans'),
(6, 'installSitePhotosfolder', 'INSTALLATION PARTNERS/SITE PHOTOS', '', 'Site Photos'),
(7, 'installChangeOrdersfolder', 'INSTALLATION PARTNERS/DOCUMENTS/CHANGE ORDERS', '', 'Change Orders'),
(8, 'installCompletionfolder', 'INSTALLATION PARTNERS/SITE PHOTOS/COMPLETION', '', 'Completion'),
(9, 'installDamagesandWarrantyfolder', 'INSTALLATION PARTNERS/SITE PHOTOS/DAMAGES & WARRANTY', '', 'Damages & Warranty'),
(10, 'installMarketingfolder', 'INSTALLATION PARTNERS/SITE PHOTOS/MARKETING', '', 'Marketing'),
(11, 'installProgressfolder', 'INSTALLATION PARTNERS/SITE PHOTOS/MARKETING', '', 'Progress'),
(12, 'meadowsfolder', 'MEADOWS PROJECT DOCUMENTS', '', 'Meadows Documents'),
(13, 'meadowsChangeOrdersfolder', 'MEADOWS PROJECT DOCUMENTS/CHANGE ORDERS', '', 'Meadows Change Orders'),
(14, 'meadowsPunchListfolder', 'MEADOWS PROJECT DOCUMENTS/PUNCHLIST', '', 'Meadows Punchlists'),
(15, 'meadowsPunchListItemsfolder', 'MEADOWS PROJECT DOCUMENTS/PUNCHLIST ITEMS', '', 'Meadows Punchlist Items');
我们的目标是实现这一目标
stdClass Object
(
[children] => Array
(
[0] => stdClass Object
(
[slug] => installfolder
[text] => INSTALLATION PARTNERS
[children] => Array
(
[0] => stdClass Object
(
[slug] => installCOIfolder
[text] => DOCUMENTS
[children] => Array
(
[0] => stdClass Object
(
[slug] => installCOIfolder
[text] => COI
[children] => Array
(
)
)
[1] => stdClass Object
(
[slug] => installDeliveryTicketsfolder
[text] => DELIVERY TICKETS
[children] => Array
(
)
)
[2] => stdClass Object
(
[slug] => installChangeOrdersfolder
[text] => CHANGE ORDERS
[children] => Array
(
)
)
)
)
[1] => stdClass Object
(
[slug] => installPdfPackagefolder
[text] => PDF INSTALLATION PACKAGE
[children] => Array
(
[0] => stdClass Object
(
[slug] => installPunchListfolder
[text] => PDF PUNCHLIST FLOORPLAN
[children] => Array
(
)
)
)
)
[2] => stdClass Object
(
[slug] => installSitePhotosfolder
[text] => SITE PHOTOS
[children] => Array
(
[0] => stdClass Object
(
[slug] => installCompletionfolder
[text] => COMPLETION
[children] => Array
(
)
)
[1] => stdClass Object
(
[slug] => installDamagesandWarrantyfolder
[text] => DAMAGES & WARRANTY
[children] => Array
(
)
)
[2] => stdClass Object
(
[slug] => installMarketingfolder
[text] => MARKETING
[children] => Array
(
)
)
)
)
)
)
[1] => stdClass Object
(
[slug] => meadowsfolder
[text] => MEADOWS PROJECT DOCUMENTS
[children] => Array
(
[0] => stdClass Object
(
[slug] => meadowsChangeOrdersfolder
[text] => CHANGE ORDERS
[children] => Array
(
)
)
[1] => stdClass Object
(
[slug] => meadowsPunchListfolder
[text] => PUNCHLIST
[children] => Array
(
)
)
[2] => stdClass Object
(
[slug] => meadowsPunchListItemsfolder
[text] => PUNCHLIST ITEMS
[children] => Array
(
)
)
)
)
)
)
现在我要做的是。我使用两个递归函数合并这个结构。这是第一个
function buildTree(array &$array, $parents, $value, $glue = '/')
{
if (!is_array($parents)) {
$parents = explode($glue, (string) $parents);
}
$ref = &$array;
foreach ($parents as $key => $parent) {
if (isset($ref) && !is_array($ref)) {
$ref = [];
}
$ref = &$ref[$parent];
}
$ref = $value;
}
$query = "SELECT * FROM validation_paths";
$results = $db->query($query);
$tree = array();
if (!empty($results)){
foreach ($results as $folder){
buildTree($tree,$folder['path_string'] . '/slug',$folder['folder']);
buildTree($tree,$folder['path_string'] . '/text',$folder['path_string']);
}
}
pruneTree($tree);
echo '<pre>';
print_r($tree);
然后我被绊倒了。我使用这个递归函数根据自己的需要修改这个结构,但没有得到好的结果
下面是函数
Array
(
[INSTALLATION PARTNERS] => Array
(
[slug] => installfolder
[text] => INSTALLATION PARTNERS
[DOCUMENTS] => Array
(
[COI] => Array
(
[slug] => installCOIfolder
[text] => COI
[children] => Array
(
)
)
[DELIVERY TICKETS] => Array
(
[slug] => installDeliveryTicketsfolder
[text] => DELIVERY TICKETS
[children] => Array
(
)
)
[CHANGE ORDERS] => Array
(
[slug] => installChangeOrdersfolder
[text] => CHANGE ORDERS
[children] => Array
(
)
)
[slug] => installCOIfolder
[text] => DOCUMENTS
[children] => Array
(
)
)
[PDF INSTALLATION PACKAGE] => Array
(
[slug] => installPdfPackagefolder
[text] => PDF INSTALLATION PACKAGE
[PDF PUNCHLIST FLOORPLAN] => Array
(
[slug] => installPunchListfolder
[text] => PDF PUNCHLIST FLOORPLAN
[children] => Array
(
)
)
[children] => Array
(
)
)
[SITE PHOTOS] => Array
(
[slug] => installSitePhotosfolder
[text] => SITE PHOTOS
[COMPLETION] => Array
(
[slug] => installCompletionfolder
[text] => COMPLETION
[children] => Array
(
)
)
[DAMAGES & WARRANTY] => Array
(
[slug] => installDamagesandWarrantyfolder
[text] => DAMAGES & WARRANTY
[children] => Array
(
)
)
[MARKETING] => Array
(
[slug] => installProgressfolder
[text] => MARKETING
[children] => Array
(
)
)
[children] => Array
(
)
)
[children] => Array
(
)
)
[MEADOWS PROJECT DOCUMENTS] => Array
(
[slug] => meadowsfolder
[text] => MEADOWS PROJECT DOCUMENTS
[CHANGE ORDERS] => Array
(
[slug] => meadowsChangeOrdersfolder
[text] => CHANGE ORDERS
[children] => Array
(
)
)
[PUNCHLIST] => Array
(
[slug] => meadowsPunchListfolder
[text] => PUNCHLIST
[children] => Array
(
)
)
[PUNCHLIST ITEMS] => Array
(
[slug] => meadowsPunchListItemsfolder
[text] => PUNCHLIST ITEMS
[children] => Array
(
)
)
[children] => Array
(
)
)
[slug] => installfolder
[text] =>
[children] => Array
(
)
)
我从中得到
function set_nested_array_value(&$array, $path, &$value, $delimiter = '/') {
$pathParts = explode($delimiter, $path);
$current = &$array;
foreach($pathParts as $key) {
$current = &$current[$key];
}
$backup = $current;
$current = $value;
return $backup;
}
谁能给我一个正确方向的提示?谢谢。首先,有其他方法可以做到这一点,但为了保持您的工作流程,我将修改
buildTree
函数来存储所有需要的数据。为此,您可以使用以下答案:
现在您可以调用此函数并使用该值存储slug,在本例中,我使用['folder'=>$path['folder']]
,因此现在您有:
function pruneTree( $array){
$result = []; $i = 0;
foreach($array as $key=>$node){
$r = [];
// set the slug if it exists
if(isset( $node['folder'])){
$r['slug'] = $node['folder'];
unset($node['folder']);
}
$r['text'] = $key;
// set the children through recursion
$r['children'] = pruneTree($node);
// when the node does not have slug (ie: DOCUMENTS)
// set the slug of the first child - to match expected results.
if(!isset($r['slug']) && isset($r['children'][0])){
$r['slug'] = $r['children'][0]->slug;
}
// transform to object - to match expected results.
$result[$i] =(object) $r;
$i++;
}
return $result;
}
然后修改pruneTree
以创建stdClass对象及其子对象:
$r = [
'children' => pruneTree(buildTree($results))
];
print_r((object)$r);
现在,为了符合您的预期结果,您可以执行以下操作:
function buildTree($data) {
$tree = new StdClass;
$index = [];
foreach ($data as $item) {
$node = $tree;
$path = '';
foreach (explode('/', $item['path_string']) as $segment) {
$path .= empty($path) ? $segment : '/' . $segment;
if (!isset($index[$path])) {
$index[$path] = new stdClass;
$index[$path]->slug = $item['folder'];
$index[$path]->text = $segment;
$index[$path]->children = [];
$node->children[] = $index[$path]
}
$node = $index[$path];
}
}
return $tree;
}
以下是因为对象本身是作为引用传递的,所以您只需要使用路径段(关系数据)找到正确的对象。最简单的方法是使用这些路径作为索引,您可以在后续迭代中引用它们。尝试此功能:
在您的示例中,没有安装伙伴/文档的数据,因此它将保持为空节点(仅限子节点)。如果不是错误,请提供一些信息,因为我不知道如何解析其属性,以便与预期结果相匹配。谢谢您的回答,但实际上我已经开始了。没有将子项替换为路径段名称。我使用您的sql创建了表,并从中运行代码以获得您期望的结果。您是否更改了表或查询?嗨,Michael,很抱歉造成误导,它工作得很好!非常感谢。我给迈克尔写信了吗?对不起,米歇尔。我看到的唯一问题是成员的顺序在最后是“slug”,这可能会触发格式错误的json。谢谢。@www.data很乐意帮忙。是的,我的回答不包括所有情况或您可能有的任何其他要求,只是一种方法。随意修改:)非常接近!仍然在计算文档条目异常,并将子节点添加到all,即使是空的。如果这可以在一个功能中实现,那么这个答案将非常棒!非常感谢。非常感谢你的兄弟,你的方法真的很熟练!下面是一个小的编辑,它可以在一个递归函数中工作。你们应该得到一个捐款人,万分感谢。@www.data我将把它作为答案。但要小心,因为这取决于数据库中的记录顺序(这是解决空
文档节点的唯一方法)。考虑一下进入+1,注意到对象是通过引用传递的,并且在一个函数中完成了所有操作,很好地完成了。
function pruneTree( $array){
$result = []; $i = 0;
foreach($array as $key=>$node){
$r = [];
// set the slug if it exists
if(isset( $node['folder'])){
$r['slug'] = $node['folder'];
unset($node['folder']);
}
$r['text'] = $key;
// set the children through recursion
$r['children'] = pruneTree($node);
// when the node does not have slug (ie: DOCUMENTS)
// set the slug of the first child - to match expected results.
if(!isset($r['slug']) && isset($r['children'][0])){
$r['slug'] = $r['children'][0]->slug;
}
// transform to object - to match expected results.
$result[$i] =(object) $r;
$i++;
}
return $result;
}
$r = [
'children' => pruneTree(buildTree($results))
];
print_r((object)$r);
function buildTree($data) {
$tree = new StdClass;
$index = [];
foreach ($data as $item) {
$node = $tree;
$path = '';
foreach (explode('/', $item['path_string']) as $segment) {
$path .= empty($path) ? $segment : '/' . $segment;
if (!isset($index[$path])) {
$index[$path] = new stdClass;
$index[$path]->slug = $item['folder'];
$index[$path]->text = $segment;
$index[$path]->children = [];
$node->children[] = $index[$path]
}
$node = $index[$path];
}
}
return $tree;
}