I have the following array structure:
[parents] => Array
(
[0] => Array
(
[id] => 1
[user_id] => 1
[created] => 2014-11-09 13:47:37
[content] => This is a test discussion
[status] => 1
[parent] => 0
[project_id] => 1
)
[1] => Array
(
[id] => 4
[user_id] => 1
[created] => 2014-11-09 13:52:02
[content] => 456789
[status] => 1
[parent] => 0
[project_id] => 1
)
)
[children] => Array
(
[0] => Array
(
[id] => 2
[user_id] => 1
[created] => 2014-11-09 13:47:53
[content] => This is a test reply....
[status] => 1
[parent] => 1
[project_id] => 1
)
[1] => Array
(
[id] => 3
[user_id] => 1
[created] => 2014-11-09 13:48:13
[content] => This is a test reply....!!!
[status] => 1
[parent] => 1
[project_id] => 1
)
[2] => Array
(
[id] => 5
[user_id] => 1
[created] => 2014-11-09 13:52:17
[content] => 8765432
[status] => 1
[parent] => 4
[project_id] => 1
)
)
I would like to merge them into a parent/child relationship so it looks like follows:
[parents] => Array
(
[0] => Array
(
[id] => 1
[user_id] => 1
[created] => 2014-11-09 13:47:37
[content] => This is a test discussion
[status] => 1
[parent] => 0
[project_id] => 1
[children] => Array
(
[0] => Array
(
[id] => 2
[user_id] => 1
[created] => 2014-11-09 13:47:53
[content] => This is a test reply....
[status] => 1
[parent] => 1
[project_id] => 1
)
[1] => Array
(
[id] => 3
[user_id] => 1
[created] => 2014-11-09 13:48:13
[content] => This is a test reply....!!!
[status] => 1
[parent] => 1
[project_id] => 1
)
)
)
)
How could I go about doing that with PHP?
Assuming that all ids are unique in your parents array, you can do this:
// build a new array using parent's ID values as the key,
// to simplify searching for parent IDs.
foreach ($parents as $key => $value){
$merged[$value['id']] = $value;
}
foreach ($children as $child){
$parentID = $child['parent'];
if (array_key_exists( $parentID, $merged )) {
// add the child array to its parent's ['children'] value
$merged[$parentID]['children'][] = $child;
}
}
In the resulting array $merged, the key of each parent item will be set to its id, and all children will be nested under their corresponding parents.
Related
i have a big problem to u resolve, it's killing me.
See a Array response:
Array (
[category_id] => 1
[parent_id] => 0
[name] => Root Catalog
[is_active] =>
[position] => 0
[level] => 0
[children] => Array
(
[0] => Array
(
[category_id] => 2
[parent_id] => 1
[name] => AutomaBrasil
[is_active] => 1
[position] => 1
[level] => 1
[children] => Array
(
[0] => Array
(
[category_id] => 3
[parent_id] => 2
[name] => Automação
[is_active] => 1
[position] => 1
[level] => 2
[children] => Array
(
)
)
[1] => Array
(
[category_id] => 4
[parent_id] => 2
[name] => Balança
[is_active] => 1
[position] => 2
[level] => 2
[children] => Array
(
)
)
[2] => Array
(
[category_id] => 5
[parent_id] => 2
[name] => Caixa Registradora
[is_active] => 1
[position] => 3
[level] => 2
[children] => Array
(
)
)
[3] => Array
(
[category_id] => 6
[parent_id] => 2
[name] => Gaveta de Dinheiro
[is_active] => 1
[position] => 4
[level] => 2
[children] => Array
(
[0] => Array
(
[category_id] => 10
[parent_id] => 6
[name] => Acessórios
[is_active] => 1
[position] => 1
[level] => 3
[children] => Array
(
)
)
[1] => Array
(
[category_id] => 12
[parent_id] => 6
[name] => Gaveta de Dinheiro Automática
[is_active] => 1
[position] => 2
[level] => 3
[children] => Array
(
)
)
)
)
[4] => Array
(
[category_id] => 7
[parent_id] => 2
[name] => Impressora
[is_active] => 1
[position] => 5
[level] => 2
[children] => Array
(
)
)
)
)
))
Until then beauty, but when i try the "foreach", it returns me this:
1
0
Root Catalog
0
0
Array
I need it to print the complete tree inside the tags <ul> <li>.
I'm use recursive foreach:
public function createTree($lists) {
echo '<ul>';
foreach ($lists as $list) {
echo '<li>';
echo $list['name'] . '';
echo '</li>';
if (is_array($list['children'])) {
$this->createTree($list['children']);
}
}
echo '</ul>';
}
U can help me? Tks!
You could try to wrap the output children array into li:
Wrap the $this->createTree($list['children'] into echo '<li>'; $this->createTree($list['children']); echo '</li>'
I have a long array from which I wish to fetch all the values and store it in a separate variable, and store each value in database.
The array that I have is:
Array
(
[success] => 1
[categories] => Array
(
[0] => Array
(
[category_id] => 39
[name] => BAGS
[categories] => Array
(
[0] => Array
(
[category_id] => 59
[name] => Handcrafted Purses
[categories] =>
[status] => 1
)
[1] => Array
(
[category_id] => 45
[parent_id] => 39
[name] => Laptop Bag
[categories] =>
[status] => 1
)
)
[status] => 1
)
[1] => Array
(
[category_id] => 40
[name] => BOXERS
[categories] => Array
(
[0] => Array
(
[category_id] => 56
[parent_id] => 40
[name] => Women Boxers
[status] => 1
)
)
[status] => 1
)
[2] => Array
(
[category_id] => 91
[parent_id] => 0
[name] => Business Corporate
[image] =>
[categories] => Array
(
[0] => Array
(
[category_id] => 92
[parent_id] => 91
[name] => Bags
[image] =>
[categories] => Array
(
[0] => Array
(
[category_id] => 93
[parent_id] => 92
[name] => Potli Bags
[image] =>
[categories] =>
[status] => 1
)
)
[status] => 1
)
)
[status] => 1
)
[3] => Array
(
[category_id] => 60
[parent_id] => 0
[name] => Business Corporates
[image] =>
[categories] => Array
(
[0] => Array
(
[category_id] => 90
[parent_id] => 60
[name] => Art Cushions
[image] =>
[categories] =>
[status] => 1
)
[1] => Array
(
[category_id] => 67
[parent_id] => 60
[name] => Bags
[image] =>
[categories] => Array
(
[0] => Array
(
[category_id] => 77
[parent_id] => 67
[name] => Potli Bags
[image] =>
[categories] =>
[status] => 1
)
[1] => Array
(
[category_id] => 76
[parent_id] => 67
[name] => Smart Bags
[image] =>
[categories] =>
[status] => 1
)
)
[status] => 1
)
[2] => Array
(
[category_id] => 86
[parent_id] => 60
[name] => Fashion Jewellery
[image] =>
[categories] => Array
(
[0] => Array
(
[category_id] => 88
[parent_id] => 86
[name] => Coming Soon - Products Uploading
[image] =>
[categories] =>
[status] => 1
)
)
[status] => 1
)
[3] => Array
(
[category_id] => 61
[parent_id] => 60
[name] => Men Footwear
[image] =>
[categories] => Array
(
[0] => Array
(
[category_id] => 65
[parent_id] => 61
[name] => Canvas Loafers
[image] =>
[categories] =>
[status] => 1
)
)
[status] => 1
)
[4] => Array
(
[category_id] => 87
[parent_id] => 60
[name] => Shawls And Stoles
[image] =>
[categories] => Array
(
[0] => Array
(
[category_id] => 89
[parent_id] => 87
[name] => Coming Soon - Products Uploading
[image] =>
[categories] =>
[status] => 1
)
)
[status] => 1
)
)
[status] => 1
)
[4] => Array
(
[category_id] => 15
[parent_id] => 0
[name] => ETHNIC WEAR
[image] =>
[categories] => Array
(
[0] => Array
(
[category_id] => 28
[parent_id] => 15
[name] => Designer Lehngas
[image] =>
[categories] =>
[status] => 1
)
[1] => Array
(
[category_id] => 2
[parent_id] => 15
[name] => Suits
[image] =>
[categories] =>
[status] => 1
)
)
[status] => 1
)
)
)
I am able to fetch the outer values of this array by using this code:
if (!empty($array))
{
foreach ($array['categories'] as $category)
{
echo $category['category_id'];
echo "<br>";
}
}
I got values as:
39
40
91
60
15
16
38
57
But I also wish to access the inner most values of the array. Can anyone tell how I can create a nested loop?
If you now how deep your array is you can just simply add other foreach-loops within your main loop.
if (!empty($array))
{
foreach ($array['categories'] as $category)
{
echo $category['category_id'];
echo "<br>";
if(isset($category['categories'])){
foreach($category['categories'] as $category2)
{
echo $category2['category_id'];
echo "<br>";
if (isset($category2['categories'])){
foreach($category2['categories'] as $category3)
{
echo $category3['category_id'];
echo "<br>";
...
} }
}}
}
}
Its generally related to a question in magento ..but i think using core php can also give me a wat i want
Im having a looping array issue here,My aray is like this
Array
(
[0] => Array
(
[category_id] => 2
[parent_id] => 1
[name] => Koffersenkisten
[is_active] => 0
[position] => 1
[level] => 1
[children] => Array
(
[0] => Array
(
[category_id] => 40
[parent_id] => 2
[name] => Muziek
[is_active] => 1
[position] => 1
[level] => 2
[children] => Array
(
[0] => Array
(
[category_id] => 46
[parent_id] => 40
[name] => Gitaar koffer
[is_active] => 1
[position] => 1
[level] => 3
[children] => Array
(
[0] => Array
(
[category_id] => 50
[parent_id] => 46
[name] => Bas gitaar koffer
[is_active] => 1
[position] => 1
[level] => 4
[children] => Array
(
)
)
[1] => Array
(
[category_id] => 51
[parent_id] => 46
[name] => Electrische gitaar koffer
[is_active] => 1
[position] => 2
[level] => 4
[children] => Array
(
)
)
[2] => Array
(
[category_id] => 47
[parent_id] => 46
[name] => Akoestische gitaar koffer
[is_active] => 1
[position] => 3
[level] => 4
[children] => Array
(
)
)
[3] => Array
(
[category_id] => 49
[parent_id] => 46
[name] => Gitaar soft cases
[is_active] => 1
[position] => 4
[level] => 4
[children] => Array
(
)
)
[4] => Array
(
[category_id] => 52
[parent_id] => 46
[name] => Gitaar gig bags
[is_active] => 1
[position] => 5
[level] => 4
[children] => Array
(
)
)
[5] => Array
(
[category_id] => 53
[parent_id] => 46
[name] => Pedalboards
[is_active] => 1
[position] => 6
[level] => 4
[children] => Array
(
)
)
[6] => Array
(
[category_id] => 48
[parent_id] => 46
[name] => Amp Utility Vehicles
[is_active] => 1
[position] => 7
[level] => 4
[children] => Array
(
)
)
)
)
[1] => Array
(
[category_id] => 67
[parent_id] => 40
[name] => Percussie koffer
[is_active] => 1
[position] => 2
[level] => 3
[children] => Array
(
[0] => Array
(
[category_id] => 73
[parent_id] => 67
[name] => Tom koffer
[is_active] => 1
[position] => 1
[level] => 4
[children] => Array
(
)
)
.......
......
>> it goes like this based on the number of categories
How do i get a simple array of the above like this
array('2' => 'Koffersenkisten','40'=> 'Muziek'...........etc); where 2 is the category_id and Koffersenkisten is the name
This function iterates over all items, and recurses when children are found. It passes the output array along at every invocation and appends to it:
function get_cats(array &$output, array $arr)
{
foreach ($arr as $item) {
$output[$item['category_id']] = $item['name'];
if (count($item['children'])) {
get_cats($output, $item['children']);
}
}
}
// start with empty result
$output = array();
get_cats($output, $a);
print_r($output);
This should work. Didn't test it.
$result = array();
function buildArray($array, $stack)
{
foreach($array as $item)
{
$stack[$item['category_id']] = $item['name'];
if(isset($item['children']) && count($item['children']) > 0)
foreach($item['children'] as $child)
buildArray($item['children'], &$stack);
}
}
buildArray($array, &$result);
print_r($result);
Here is a recursive solution (the array should be in $list before, the created array will be in $result after calling the create function):
function create($list, &$result) {
if (is_array($list) && !isset($list['category_id'])) {
foreach ($list as $element) {
create($element, $result);
}
} else {
$result[$list['category_id']] = $list['name'];
create($list['children'], $result);
}
}
create($list, $result);
Also see this example.
I have an array of categories where id is the id of the category, parent denotes the parent id of the category (id 0 denotes the top most parent node) and value is the title of the array. The path is initially set to the id of the category. The array is as follows:
Array
(
[0] => Array
(
[id] => 1
[parent] => 0
[value] => Corporate Files
[path] => 1
)
[1] => Array
(
[id] => 2
[parent] => 0
[value] => Products Files
[path] => 2
)
[2] => Array
(
[id] => 3
[parent] => 1
[value] => Communications Materials
[path] => 3
)
[3] => Array
(
[id] => 4
[parent] => 1
[value] => Group Technical
[path] => 4
)
[4] => Array
(
[id] => 5
[parent] => 1
[value] => New Projects
[path] => 5
)
[5] => Array
(
[id] => 6
[parent] => 2
[value] => Product Range
[path] => 6
)
[6] => Array
(
[id] => 7
[parent] => 2
[value] => WL4
[path] => 7
)
);
I want to generate the paths of categories in the array. so the output should be
Array
(
[0] => Array
(
[id] => 1
[parent] => 0
[value] => Corporate Files
[path] => 1
)
[1] => Array
(
[id] => 2
[parent] => 0
[value] => Products Files
[path] => 2
)
[2] => Array
(
[id] => 3
[parent] => 1
[value] => Communications Materials
[path] => 1,3
)
[3] => Array
(
[id] => 4
[parent] => 1
[value] => Group Technical
[path] => 1,4
)
[4] => Array
(
[id] => 5
[parent] => 1
[value] => New Projects
[path] => 1,5
)
[5] => Array
(
[id] => 6
[parent] => 2
[value] => Product Range
[path] => 2,6
)
[6] => Array
(
[id] => 7
[parent] => 2
[value] => WL4
[path] => 2,7
)
);
I wrote the following function.
function findparent($id,$path){
global $categories;
global $catcnt;
if($id==0){
echo $path."<br />"; //this outputs path currently
return $path;
}
for($i=0;$i<$catcnt;$i++){
if($id==$categories[$i]['id']){
$path=$id.",".$path;
findparent($categories[$i]['parent'],$path);
}
}
}
for($i=0;$i<count($categories);$i++){
$categories[$i]['path']=(string)findparent($categories[$i]['parent'],$categories[$i]['id']); //this doesnt assign it currectly
}
and the output is:
Array
(
[0] => Array
(
[id] => 1
[parent] => 0
[value] => Corporate Files
[path] =>
)
[1] => Array
(
[id] => 2
[parent] => 0
[value] => Products Files
[path] =>
)
[2] => Array
(
[id] => 3
[parent] => 1
[value] => Communications Materials
[path] =>
)
[3] => Array
(
[id] => 4
[parent] => 1
[value] => Group Technical
[path] =>
)
[4] => Array
(
[id] => 5
[parent] => 1
[value] => New Projects
[path] =>
)
[5] => Array
(
[id] => 6
[parent] => 2
[value] => Product Range
[path] =>
)
[6] => Array
(
[id] => 7
[parent] => 2
[value] => WL4
[path] =>
)
);
Where am I going wrong?
findparent only returns if the id is zero.
You need a second return statement, before the recursive findparent call.
As you don't need to deal with multiple levels, a function of it's own is a bit of an overhead as you could work straight on the array itself with a simple foreach:
foreach ($array as &$node)
{
if ($node['parent'])
{
$node['path'] = $node['parent'] . ',' . $node['path'];
}
}
unset($node);
However, you can put this into a function of it's own as well, but you won't need any global variables as far as I can see.
What you see here is simple string concatenation, this makes the array as you wrote you wanted it to have. My first comment was more meant to manage the structure with an n-depth not a 1-depth. Demo
I've got an array with data from a MySQL table in nested set model I'd like to get sorted, not only alphabetical but also with the child nodes directly after the parent node.
Example - array to be sorted (before the sorting):
Array
(
[0] => Array
(
[id] => 1
[name] => Kompetenser
[parent] => 0
[depth] => 0
)
[1] => Array
(
[id] => 2
[name] => Administration
[parent] => 1
[depth] => 1
)
[2] => Array
(
[id] => 11
[name] => Organisation
[parent] => 2
[depth] => 2
)
[3] => Array
(
[id] => 4
[name] => Arbetsledning
[parent] => 2
[depth] => 2
)
[4] => Array
(
[id] => 17
[name] => Planering
[parent] => 2
[depth] => 2
)
[5] => Array
(
[id] => 9
[name] => Hantverke
[parent] => 1
[depth] => 1
)
[6] => Array
(
[id] => 10
[name] => Snickeri
[parent] => 9
[depth] => 2
)
[7] => Array
(
[id] => 12
[name] => Språk
[parent] => 1
[depth] => 1
)
[8] => Array
(
[id] => 13
[name] => Tolk
[parent] => 12
[depth] => 2
)
[9] => Array
(
[id] => 15
[name] => Arabiska
[parent] => 13
[depth] => 3
)
[10] => Array
(
[id] => 14
[name] => Persiska
[parent] => 13
[depth] => 3
)
[11] => Array
(
[id] => 16
[name] => Polska
[parent] => 13
[depth] => 3
)
[12] => Array
(
[id] => 18
[name] => Apotekare
[parent] => 1
[depth] => 1
)
[13] => Array
(
[id] => 19
[name] => Dotkorand
[parent] => 1
[depth] => 1
)
[14] => Array
(
[id] => 21
[name] => Atomfysik
[parent] => 19
[depth] => 2
)
[15] => Array
(
[id] => 20
[name] => Fysik
[parent] => 19
[depth] => 2
)
[16] => Array
(
[id] => 22
[name] => Ekonom
[parent] => 1
[depth] => 1
)
[17] => Array
(
[id] => 23
[name] => Industriell ekonomi
[parent] => 22
[depth] => 2
)
[18] => Array
(
[id] => 24
[name] => Filosofi
[parent] => 1
[depth] => 1
)
)
I want the array this way (after the sorting):
Array
(
[0] => Array
(
[id] => 1
[name] => Kompetenser
[parent] => 0
[depth] => 0
)
[1] => Array
(
[id] => 2
[name] => Administration
[parent] => 1
[depth] => 1
)
[3] => Array
(
[id] => 4
[name] => Arbetsledning
[parent] => 2
[depth] => 2
)
[2] => Array
(
[id] => 11
[name] => Organisation
[parent] => 2
[depth] => 2
)
[4] => Array
(
[id] => 17
[name] => Planering
[parent] => 2
[depth] => 2
)
[12] => Array
(
[id] => 18
[name] => Apotekare
[parent] => 1
[depth] => 1
)
[13] => Array
(
[id] => 19
[name] => Dotkorand
[parent] => 1
[depth] => 1
)
[14] => Array
(
[id] => 21
[name] => Atomfysik
[parent] => 19
[depth] => 2
)
[15] => Array
(
[id] => 20
[name] => Fysik
[parent] => 19
[depth] => 2
)
[16] => Array
(
[id] => 22
[name] => Ekonom
[parent] => 1
[depth] => 1
)
[17] => Array
(
[id] => 23
[name] => Industriell ekonomi
[parent] => 22
[depth] => 2
)
[18] => Array
(
[id] => 24
[name] => Filosofi
[parent] => 1
[depth] => 1
)
[5] => Array
(
[id] => 9
[name] => Hantverke
[parent] => 1
[depth] => 1
)
[6] => Array
(
[id] => 10
[name] => Snickeri
[parent] => 9
[depth] => 2
)
[7] => Array
(
[id] => 12
[name] => Språk
[parent] => 1
[depth] => 1
)
[8] => Array
(
[id] => 13
[name] => Tolk
[parent] => 12
[depth] => 2
)
[9] => Array
(
[id] => 15
[name] => Arabiska
[parent] => 13
[depth] => 3
)
[10] => Array
(
[id] => 14
[name] => Persiska
[parent] => 13
[depth] => 3
)
[11] => Array
(
[id] => 16
[name] => Polska
[parent] => 13
[depth] => 3
)
)
As you might see, I want all posts with parent 2 directly after the post with id 2, and so on.
Any help would be highly appreciated.
Thank you in advance.
Don't do this in PHP!
The MySQL server is specificly designed to query AND sort data, read up on the MySQL "ORDER BY" syntax. Doing this on the MySQL server will save run-time, CPU Load and Memory Consumption.
Use php's uasort() function to define your own comparison function.
But using MySQL's sorting capabilities would be more appropriate, if it's possible in your case.
You want to sort it like it is in the DB, multilayered. I don't think uasort can help with this problem because you want to attach the children to the parent.
foreach ($arr as &$val) {
$arr2[$val['id']] = &$val;
}
ksort($arr2);
foreach ($arr2 as $id => &$val) {
$parent = $val['parent'];
if ($parent == 0) {
continue;
}
$arr2[$parent]['children'][$id] = &$val;
}
function flattenArrayByChildren($arr) {
foreach ($arr as $id => $val) {
if (isset($val['children'])) {
$temp = flattenArrayByChildren($val['children']);
unset($val['children']);
$out[$id] = $val;
$out = $out + $temp;
} else {
$out[$id] = $val;
}
}
return $out;
}
$arr2 = array(1 => $arr2[1]);
$out = flattenArrayByChildren($arr2);
var_dump($out);
If you absolutely want to save the key, you can just add that to the $val in the first foreach, and retrieve it in the recursive function flattenArrayByChildren and use as key.
Problem solved - I made two simple functions. I hope other people could have use of this as well:
class data_comp
{
var $fetched_tree = array();
function tree_fetch($parent = 0)
{
$query = 'SELECT node.id, node.name, node.parent, (COUNT(parent.name) - 1) AS depth FROM test_competence AS node, test_competence AS parent WHERE node.lft BETWEEN parent.lft AND parent.rgt GROUP BY node.name ORDER BY node.name';
$result = mysql_query($query) or die(mysql_error());
$tree = array();
while($data = mysql_fetch_assoc($result))
{
$tree[$data['parent']][$data['id']] = array('name' => $data['name'], 'depth' => $data['depth']);
}
$this->tree_print($tree, $parent);
}
function tree_print($tree, $parent)
{
foreach($tree[$parent] as $id => $value)
{
$this->fetched_tree[] = array('id' => $id, 'name' => $value['name'], 'depth' => $value['depth']);
if(isset($tree[$id]) && is_array($tree[$id]))
{
$this->tree_print($tree, $id);
}
}
}
}
Thank you for your time. Any improvements are more than welcome.