PHP使用关系数据创建多维数组[duplicate]

时间:2021-12-29 21:21:11

Possible Duplicate:
Converting an array from one to multi-dimensional based on parent ID values

可能的重复:基于父ID值将数组从1转换为多维

I am working in PHP.

我用的是PHP。

I have the following array that has relational data (parent child relationships).

我有以下具有关系数据(父子关系)的数组。

Array        
(        
    [5273] => Array        
        (        
            [id] => 5273        
            [name] => John Doe        
            [parent] =>         
        )        

    [6032] => Array        
        (        
            [id] => 6032        
            [name] => Sally Smith        
            [parent] => 5273        
        )        

    [6034] => Array        
        (        
            [id] => 6034        
            [name] => Mike Jones        
            [parent] => 6032        
        )        

    [6035] => Array        
        (        
            [id] => 6035        
            [name] => Jason Williams        
            [parent] => 6034        
        )        

    [6036] => Array        
        (        
            [id] => 6036        
            [name] => Sara Johnson        
            [parent] => 5273        
        )        

    [6037] => Array        
        (        
            [id] => 6037        
            [name] => Dave Wilson        
            [parent] => 5273        
        )        

    [6038] => Array        
        (        
            [id] => 6038        
            [name] => Amy Martin        
            [parent] => 6037        
        )        
)        

I need it to be in this JSON format:

我需要它是这个JSON格式:

{        
   "id":"5273",        
   "name":"John Doe",        
   "data":{        

   },        
   "children":[        
      {        
         "id":" Sally Smith",        
         "name":"6032",        
         "data":{        

         },        
         "children":[        
            {        
               "id":"6034",        
               "name":"Mike Jones",        
               "data":{        

               },        
               "children":[        
                  {        
                     "id":"6035",        
                     "name":"Jason Williams",        
                     "data":{        

                     },        
                     "children":[        
                        {        
                           "id":"node46",        
                           "name":"4.6",        
                           "data":{        

                           },        
                           "children":[        

                           ]        
                        }        
                     ]        
                  }        
               ]        
            },        
            {        
               "id":"6036",        
               "name":"Sara Johnson",        
               "data":{        

               },        
               "children":[        

               ]        
            },        
            {        
               "id":"6037",        
               "name":"Dave Wilson",        
               "data":{        

               },        
               "children":[        
                  {        
                     "id":"6038",        
                     "name":"Amy Martin",        
                     "data":{        

                     },        
                     "children":[        

                     ]        
                  }        
               ]        
            }        
         ]        
      }        
   ]        
}        

I know I need to create a multidimensional array and run it through json_encode(). I also believe this method used to do this needs to be recursive because the real world data could have an unknown number of levels.

我知道我需要创建一个多维数组并通过json_encode()运行它。我还认为,用于实现此目的的方法需要递归,因为实际数据可能具有未知的级别。

I would be glad to show some of my approaches but they have not worked.

我很乐意展示我的一些方法,但它们没有奏效。

Can anyone help me?

谁能帮我吗?

I was asked to share my work. This is what I have tried but I have not gotten that close to I don't know how helpful it is.

我被要求分享我的工作。这是我尝试过的,但我还没有接近,我不知道它有多大的帮助。

I made an array of just the relationships.

我做了一系列的关系。

foreach($array as $k => $v){
    $relationships[$v['id']] = $v['parent'];
}

I think (based off another SO post) used this relational data to create a the new multidimensional array. If I got this to work I was going to work on adding in the correct "children" labels etc.

我认为(基于另一个SO post)使用这个关系数据创建了一个新的多维数组。如果我成功了,我将致力于添加正确的“儿童”标签等等。

$childrenTable = array();
    $data = array();
    foreach ($relationships as $n => $p) {
      //parent was not seen before, put on root
      if (!array_key_exists($p, $childrenTable)) {
          $childrenTable[$p] = array();
          $data[$p] = &$childrenTable[$p];  
      }
      //child was not seen before
      if (!array_key_exists($n, $childrenTable)) {
          $childrenTable[$n] = array();
      }
      //root node has a parent after all, relocate
      if (array_key_exists($n, $data)) {
          unset($data[$n]);
      }
      $childrenTable[$p][$n] = &$childrenTable[$n];      
    }
    unset($childrenTable);

print_r($data);

3 个解决方案

#1


12  

<?php
header('Content-Type: application/json; charset="utf-8"');

/**
 * Helper function
 * 
 * @param array   $d   flat data, implementing a id/parent id (adjacency list) structure
 * @param mixed   $r   root id, node to return
 * @param string  $pk  parent id index
 * @param string  $k   id index
 * @param string  $c   children index
 * @return array
 */
function makeRecursive($d, $r = 0, $pk = 'parent', $k = 'id', $c = 'children') {
  $m = array();
  foreach ($d as $e) {
    isset($m[$e[$pk]]) ?: $m[$e[$pk]] = array();
    isset($m[$e[$k]]) ?: $m[$e[$k]] = array();
    $m[$e[$pk]][] = array_merge($e, array($c => &$m[$e[$k]]));
  }

  return $m[$r][0]; // remove [0] if there could be more than one root nodes
}

echo json_encode(makeRecursive(array(
  array('id' => 5273, 'parent' => 0,    'name' => 'John Doe'),  
  array('id' => 6032, 'parent' => 5273, 'name' => 'Sally Smith'),
  array('id' => 6034, 'parent' => 6032, 'name' => 'Mike Jones'),
  array('id' => 6035, 'parent' => 6034, 'name' => 'Jason Williams'),
  array('id' => 6036, 'parent' => 5273, 'name' => 'Sara Johnson'),
  array('id' => 6037, 'parent' => 5273, 'name' => 'Dave Wilson'),
  array('id' => 6038, 'parent' => 6037, 'name' => 'Amy Martin'),
)));

demo: https://3v4l.org/s2PNC

演示:https://3v4l.org/s2PNC

#2


3  

Okay, this is how it works, you were actually not too far off as you started, but what you actually look for are references. This is a general procedure:

好的,这就是它的工作原理,你开始的时候其实离得不太远,但是你真正要找的是参考资料。这是一个一般程序:

As there is a relation between parent and child-nodes on their ID, you first need to index the data based on the ID. I do this here with an array ($rows) to simulate your data access, if you read from the database, it would be similar. With this indexing you can also add additional properties like your empty data:

由于父节点和子节点在ID上有关系,所以您首先需要根据ID对数据进行索引,我在这里用数组($rows)来模拟数据访问,如果您从数据库中读取数据,那么它将是相似的。通过这个索引,您还可以添加额外的属性,如您的空数据:

// create an index on id
$index = array();
foreach($rows as $row)
{
    $row['data'] = (object) array();
    $index[$row['id']] = $row;
}

So now all entries are indexed on their ID. This was the first step.

现在所有的条目都被编入了索引,这是第一步。

The second step is equally straight forward. Because we now can access each node based on it's ID in the $index, we can assign the children to their parent.

第二步同样直截了当。因为我们现在可以基于$索引中的ID访问每个节点,所以我们可以将子节点分配给它们的父节点。

There is one "virtual" node, that is the one with the ID 0. It does not exists in any of the rows, however, if we could add children to it too, we can use this children collection as the store for all root nodes, in your case, there is a single root node.

有一个“虚拟”节点,即ID为0的节点。它在任何行中都不存在,但是,如果我们可以向它添加子节点,我们可以使用这个子集合作为所有根节点的存储,在您的示例中,有一个根节点。

Sure, for the ID 0, we should not process the parent - because it does not exists.

当然,对于ID 0,我们不应该处理父类——因为它不存在。

So let's do that. We make use of references here because otherwise the same node could not be both parent and child:

让我们这样做。我们在这里使用了引用,因为否则同一个节点不能同时是父节点和子节点:

// build the tree
foreach($index as $id => &$row)
{
    if ($id === 0) continue;
    $parent = $row['parent'];
    $index[$parent]['children'][] = &$row;
}
unset($row);

Because we use references, the last line takes care to unset the reference stored in $row after the loop.

因为我们使用引用,所以最后一行要注意在循环之后取消$row中存储的引用。

Now all children have been assigned to their parents. That could it be already, however lets not forget the last step, the actual node for the output should be accessed.

现在所有的孩子都被分配给他们的父母。这是可能的,但是不要忘记最后一步,应该访问输出的实际节点。

For brevity, just assign the root node to the $index itself. If we remember, the only root node we want is the first one in the children array in the node with the ID 0:

为了简便起见,只需将根节点分配给$index本身。如果我们记得,我们想要的唯一根节点是ID为0的节点的子数组中的第一个节点:

// obtain root node
$index = $index[0]['children'][0];

And that's it. We can use it now straight away to generate the JSON:

就是这样。我们现在可以直接使用它生成JSON:

// output json
header('Content-Type: application/json');
echo json_encode($index);

Finally the whole code at a glance:

最后,整个代码一目了然:

<?php
/**
 * @link http://*.com/questions/11239652/php-create-a-multidimensional-array-from-an-array-with-relational-data
 */

$rows = array(
    array('id' => 5273, 'parent' => 0,    'name' => 'John Doe'),
    array('id' => 6032, 'parent' => 5273, 'name' => 'Sally Smith'),
    array('id' => 6034, 'parent' => 6032, 'name' => 'Mike Jones'),
    array('id' => 6035, 'parent' => 6034, 'name' => 'Jason Williams'),
    array('id' => 6036, 'parent' => 5273, 'name' => 'Sara Johnson'),
    array('id' => 6037, 'parent' => 5273, 'name' => 'Dave Wilson'),
    array('id' => 6038, 'parent' => 6037, 'name' => 'Amy Martin'),
);

// create an index on id
$index = array();
foreach($rows as $row)
{
    $row['data'] = (object) [];
    $index[$row['id']] = $row;
}

// build the tree
foreach($index as $id => &$row)
{
    if ($id === 0) continue;
    $parent = $row['parent'];
    $index[$parent]['children'][] = &$row;
}
unset($row);

// obtain root node
$index = $index[0]['children'][0];

// output json
header('Content-Type: application/json');
echo json_encode($index, JSON_PRETTY_PRINT);

Which would create the following json (here with PHP 5.4s' JSON_PRETTY_PRINT):

它将创建以下json(这里是PHP 5.4s' JSON_PRETTY_PRINT):

{
    "id": 5273,
    "parent": 0,
    "name": "John Doe",
    "data": {

    },
    "children": [
        {
            "id": 6032,
            "parent": 5273,
            "name": "Sally Smith",
            "data": {

            },
            "children": [
                {
                    "id": 6034,
                    "parent": 6032,
                    "name": "Mike Jones",
                    "data": {

                    },
                    "children": [
                        {
                            "id": 6035,
                            "parent": 6034,
                            "name": "Jason Williams",
                            "data": {

                            }
                        }
                    ]
                }
            ]
        },
        {
            "id": 6036,
            "parent": 5273,
            "name": "Sara Johnson",
            "data": {

            }
        },
        {
            "id": 6037,
            "parent": 5273,
            "name": "Dave Wilson",
            "data": {

            },
            "children": [
                {
                    "id": 6038,
                    "parent": 6037,
                    "name": "Amy Martin",
                    "data": {

                    }
                }
            ]
        }
    ]
}

#3


2  

Following code will do the job.. you may want to tweak a bit according to your needs.

下面的代码将完成这项工作。你可以根据自己的需要稍微调整一下。

$data = array(
    '5273' => array( 'id' =>5273, 'name'=> 'John Doe', 'parent'=>''),
    '6032' => array( 'id' =>6032, 'name'=> 'Sally Smith', 'parent'=>'5273'),
    '6034' => array( 'id' =>6034, 'name'=> 'Mike Jones ', 'parent'=>'6032'),
    '6035' => array( 'id' =>6035, 'name'=> 'Jason Williams', 'parent'=>'6034')
    );

$fdata = array();


function ConvertToMulti($data) {
    global $fdata;

    foreach($data as $k => $v)
    {
        if(empty($v['parent'])){
            unset($v['parent']);
        $v['data'] = array();
        $v['children'] = array();
            $fdata[] = $v;
        }
        else {
            findParentAndInsert($v, $fdata);
        }

    }
}

function findParentAndInsert($idata, &$ldata) {

    foreach ($ldata as $k=>$v) {

        if($ldata[$k]['id'] == $idata['parent']) {
            unset($idata['parent']);
        $idata['data'] = array();
        $idata['children'] = array();
            $ldata[$k]['children'][] = $idata;
            return;
        }
        else if(!empty($v['children']))
            findParentAndInsert($idata, $ldata[$k]['children']);
    }
}


print_r($data);
ConvertToMulti($data);
echo "AFTER\n";
print_r($fdata);

http://codepad.viper-7.com/Q5Buaz

http://codepad.viper - 7. com/q5buaz

#1


12  

<?php
header('Content-Type: application/json; charset="utf-8"');

/**
 * Helper function
 * 
 * @param array   $d   flat data, implementing a id/parent id (adjacency list) structure
 * @param mixed   $r   root id, node to return
 * @param string  $pk  parent id index
 * @param string  $k   id index
 * @param string  $c   children index
 * @return array
 */
function makeRecursive($d, $r = 0, $pk = 'parent', $k = 'id', $c = 'children') {
  $m = array();
  foreach ($d as $e) {
    isset($m[$e[$pk]]) ?: $m[$e[$pk]] = array();
    isset($m[$e[$k]]) ?: $m[$e[$k]] = array();
    $m[$e[$pk]][] = array_merge($e, array($c => &$m[$e[$k]]));
  }

  return $m[$r][0]; // remove [0] if there could be more than one root nodes
}

echo json_encode(makeRecursive(array(
  array('id' => 5273, 'parent' => 0,    'name' => 'John Doe'),  
  array('id' => 6032, 'parent' => 5273, 'name' => 'Sally Smith'),
  array('id' => 6034, 'parent' => 6032, 'name' => 'Mike Jones'),
  array('id' => 6035, 'parent' => 6034, 'name' => 'Jason Williams'),
  array('id' => 6036, 'parent' => 5273, 'name' => 'Sara Johnson'),
  array('id' => 6037, 'parent' => 5273, 'name' => 'Dave Wilson'),
  array('id' => 6038, 'parent' => 6037, 'name' => 'Amy Martin'),
)));

demo: https://3v4l.org/s2PNC

演示:https://3v4l.org/s2PNC

#2


3  

Okay, this is how it works, you were actually not too far off as you started, but what you actually look for are references. This is a general procedure:

好的,这就是它的工作原理,你开始的时候其实离得不太远,但是你真正要找的是参考资料。这是一个一般程序:

As there is a relation between parent and child-nodes on their ID, you first need to index the data based on the ID. I do this here with an array ($rows) to simulate your data access, if you read from the database, it would be similar. With this indexing you can also add additional properties like your empty data:

由于父节点和子节点在ID上有关系,所以您首先需要根据ID对数据进行索引,我在这里用数组($rows)来模拟数据访问,如果您从数据库中读取数据,那么它将是相似的。通过这个索引,您还可以添加额外的属性,如您的空数据:

// create an index on id
$index = array();
foreach($rows as $row)
{
    $row['data'] = (object) array();
    $index[$row['id']] = $row;
}

So now all entries are indexed on their ID. This was the first step.

现在所有的条目都被编入了索引,这是第一步。

The second step is equally straight forward. Because we now can access each node based on it's ID in the $index, we can assign the children to their parent.

第二步同样直截了当。因为我们现在可以基于$索引中的ID访问每个节点,所以我们可以将子节点分配给它们的父节点。

There is one "virtual" node, that is the one with the ID 0. It does not exists in any of the rows, however, if we could add children to it too, we can use this children collection as the store for all root nodes, in your case, there is a single root node.

有一个“虚拟”节点,即ID为0的节点。它在任何行中都不存在,但是,如果我们可以向它添加子节点,我们可以使用这个子集合作为所有根节点的存储,在您的示例中,有一个根节点。

Sure, for the ID 0, we should not process the parent - because it does not exists.

当然,对于ID 0,我们不应该处理父类——因为它不存在。

So let's do that. We make use of references here because otherwise the same node could not be both parent and child:

让我们这样做。我们在这里使用了引用,因为否则同一个节点不能同时是父节点和子节点:

// build the tree
foreach($index as $id => &$row)
{
    if ($id === 0) continue;
    $parent = $row['parent'];
    $index[$parent]['children'][] = &$row;
}
unset($row);

Because we use references, the last line takes care to unset the reference stored in $row after the loop.

因为我们使用引用,所以最后一行要注意在循环之后取消$row中存储的引用。

Now all children have been assigned to their parents. That could it be already, however lets not forget the last step, the actual node for the output should be accessed.

现在所有的孩子都被分配给他们的父母。这是可能的,但是不要忘记最后一步,应该访问输出的实际节点。

For brevity, just assign the root node to the $index itself. If we remember, the only root node we want is the first one in the children array in the node with the ID 0:

为了简便起见,只需将根节点分配给$index本身。如果我们记得,我们想要的唯一根节点是ID为0的节点的子数组中的第一个节点:

// obtain root node
$index = $index[0]['children'][0];

And that's it. We can use it now straight away to generate the JSON:

就是这样。我们现在可以直接使用它生成JSON:

// output json
header('Content-Type: application/json');
echo json_encode($index);

Finally the whole code at a glance:

最后,整个代码一目了然:

<?php
/**
 * @link http://*.com/questions/11239652/php-create-a-multidimensional-array-from-an-array-with-relational-data
 */

$rows = array(
    array('id' => 5273, 'parent' => 0,    'name' => 'John Doe'),
    array('id' => 6032, 'parent' => 5273, 'name' => 'Sally Smith'),
    array('id' => 6034, 'parent' => 6032, 'name' => 'Mike Jones'),
    array('id' => 6035, 'parent' => 6034, 'name' => 'Jason Williams'),
    array('id' => 6036, 'parent' => 5273, 'name' => 'Sara Johnson'),
    array('id' => 6037, 'parent' => 5273, 'name' => 'Dave Wilson'),
    array('id' => 6038, 'parent' => 6037, 'name' => 'Amy Martin'),
);

// create an index on id
$index = array();
foreach($rows as $row)
{
    $row['data'] = (object) [];
    $index[$row['id']] = $row;
}

// build the tree
foreach($index as $id => &$row)
{
    if ($id === 0) continue;
    $parent = $row['parent'];
    $index[$parent]['children'][] = &$row;
}
unset($row);

// obtain root node
$index = $index[0]['children'][0];

// output json
header('Content-Type: application/json');
echo json_encode($index, JSON_PRETTY_PRINT);

Which would create the following json (here with PHP 5.4s' JSON_PRETTY_PRINT):

它将创建以下json(这里是PHP 5.4s' JSON_PRETTY_PRINT):

{
    "id": 5273,
    "parent": 0,
    "name": "John Doe",
    "data": {

    },
    "children": [
        {
            "id": 6032,
            "parent": 5273,
            "name": "Sally Smith",
            "data": {

            },
            "children": [
                {
                    "id": 6034,
                    "parent": 6032,
                    "name": "Mike Jones",
                    "data": {

                    },
                    "children": [
                        {
                            "id": 6035,
                            "parent": 6034,
                            "name": "Jason Williams",
                            "data": {

                            }
                        }
                    ]
                }
            ]
        },
        {
            "id": 6036,
            "parent": 5273,
            "name": "Sara Johnson",
            "data": {

            }
        },
        {
            "id": 6037,
            "parent": 5273,
            "name": "Dave Wilson",
            "data": {

            },
            "children": [
                {
                    "id": 6038,
                    "parent": 6037,
                    "name": "Amy Martin",
                    "data": {

                    }
                }
            ]
        }
    ]
}

#3


2  

Following code will do the job.. you may want to tweak a bit according to your needs.

下面的代码将完成这项工作。你可以根据自己的需要稍微调整一下。

$data = array(
    '5273' => array( 'id' =>5273, 'name'=> 'John Doe', 'parent'=>''),
    '6032' => array( 'id' =>6032, 'name'=> 'Sally Smith', 'parent'=>'5273'),
    '6034' => array( 'id' =>6034, 'name'=> 'Mike Jones ', 'parent'=>'6032'),
    '6035' => array( 'id' =>6035, 'name'=> 'Jason Williams', 'parent'=>'6034')
    );

$fdata = array();


function ConvertToMulti($data) {
    global $fdata;

    foreach($data as $k => $v)
    {
        if(empty($v['parent'])){
            unset($v['parent']);
        $v['data'] = array();
        $v['children'] = array();
            $fdata[] = $v;
        }
        else {
            findParentAndInsert($v, $fdata);
        }

    }
}

function findParentAndInsert($idata, &$ldata) {

    foreach ($ldata as $k=>$v) {

        if($ldata[$k]['id'] == $idata['parent']) {
            unset($idata['parent']);
        $idata['data'] = array();
        $idata['children'] = array();
            $ldata[$k]['children'][] = $idata;
            return;
        }
        else if(!empty($v['children']))
            findParentAndInsert($idata, $ldata[$k]['children']);
    }
}


print_r($data);
ConvertToMulti($data);
echo "AFTER\n";
print_r($fdata);

http://codepad.viper-7.com/Q5Buaz

http://codepad.viper - 7. com/q5buaz