How to create tree view hierarchy in php codeigniter? - php

I have a array like this :
Array
(
[0] => Array
(
[id] => 1
[child_name] => "Emma"
[parent_name] => "Mr Brown"
)
[1] => Array
(
[id] => 2
[child_name] => "John"
[parent_name] => "Mr Brown"
)
[2] => Array
(
[id] => 3
[child_name] => "Joseph"
[parent_name] => "Mr Thomas"
)
[3] => Array
(
[id] => 4
[child_name] => "Pretty"
[parent_name] => "Mr Thomas"
)
[4] => Array
(
[id] => 5
[child_name] => "Raphel"
[parent_name] => "Mr Brown"
)
[5] => Array
(
[id] => 6
[child_name] => "Tommy"
[parent_name] => "Mr Thomas"
)
[6] => Array
(
[id] => 7
[child_name] => "Tim"
[parent_name] => "Mr Thomas"
)
)
From this array I want to generate a view like this :
The parent_name field becomes the MainCategory and the child_name becomes the subcategory. The names have checkboxes in front of them.
How do I achieve this? I don't have much experience in php. I code in node js but this task needs this to be done in php.
How do I do this?

Try this, Here i use simple index() method and pass data to view file as an example.
You can use below code and test in your codeigniter.
Hope this will work for you.
Welcome.php (Controller)
public function index()
{
$array = [
[
'id' => 1,
'child_name' => "Emma",
'parent_name' => "Mr Brown",
],
[
'id' => 2,
'child_name' => "John",
'parent_name' => "Mr Brown",
],
[
'id' => 3,
'child_name' => "Joseph",
'parent_name' => "Mr Thomas",
],
[
'id' => 4,
'child_name' => "Pretty",
'parent_name' => "Mr Thomas",
],
[
'id' => 5,
'child_name' => "Raphel",
'parent_name' => "Mr Brown",
],
[
'id' => 6,
'child_name' => "Tommy",
'parent_name' => "Mr Thomas",
],
[
'id' => 7,
'child_name' => "Tim",
'parent_name' => "Mr Thomas",
],
[
'id' => 8,
'child_name' => "William",
'parent_name' => "",
],
];
$resultArray = [];
foreach ($array as $key => $value) {
if($value['parent_name'] != ''){
$resultArray[$value['parent_name']][] = $value;
}else{
$resultArray[$value['child_name']] = [];
}
}
$data = ['resultArray' => $resultArray];
$this->load->view('welcome_message', $data);
}
welcome_message.php (view)
<div>
<form name='sample'>
<?php
foreach ($resultArray as $parentKey => $parentValue) {
echo '<input type="checkbox" name="'.$parentKey.'" value="'.$parentKey.'">'.$parentKey.'<br>';
foreach ($parentValue as $childKey => $childValue) {
echo ' <input type="checkbox" name="'.$childValue['child_name'].'" value="'.$childValue['child_name'].'">'.$childValue['child_name'].'<br>';
}
}
?>
</form>
</div>
Output

Check this,
Loop your array, it will capture all values with same parent_name.
$result = [];
foreach ($array as $key => $value) {
$result[$value['parent_name']][] = $value['child_name']; // loop your array
}
It should work.

Related

function to make Tree like Array in to Array

I have $tree like array which made by function from the $array I need a function to make it $tree to $array back
so I need a function to make it back.
lets call it $list this time.
I will share $tree , $array and the function in below
tree like array ;
Array
(
[0] => Array
(
[id] => 1
[name] => id1
[children] => Array
(
[0] => Array
(
[id] => 2
[parent_id] => 1
[name] => id2
[children] => Array
(
[0] => Array
(
[id] => 5
[parent_id] => 2
[name] => id5
)
)
)
[1] => Array
(
[id] => 3
[parent_id] => 1
[name] => id3
[children] => Array
(
[0] => Array
(
[id] => 6
[parent_id] => 3
[name] => id6
)
[1] => Array
(
[id] => 8
[parent_id] => 3
[name] => id8
)
)
)
)
)
[1] => Array
(
[id] => 4
[name] => id4
[children] => Array
(
[0] => Array
(
[id] => 9
[parent_id] => 4
[name] => id9
[children] => Array
(
[0] => Array
(
[id] => 10
[parent_id] => 9
[name] => id10
)
)
)
)
)
[2] => Array
(
[id] => 7
[name] => id7
[children] => Array
(
)
)
)
Which made by a function from this array
$array = [
['id'=> 1, 'parent_id' => 0, 'name' => 'id1'],
['id' => 2, 'parent_id' => 1, 'name'=> 'id2'],
['id' => 3, 'parent_id' => 1, 'name'=> 'id3'],
['id' => 4, 'parent_id' => 0, 'name'=> 'id4'],
['id' => 5,'parent_id' => 2, 'name'=> 'id5'],
['id' => 6, 'parent_id' => 3, 'name'=> 'id6'],
['id' => 7, 'parent_id' => 0, 'name'=> 'id7'],
['id' => 8, 'parent_id' => 3, 'name'=> 'id8'],
['id' => 9, 'parent_id' => 4, 'name'=> 'id9'],
['id' => 10, 'parent_id' => 9, 'name'=> 'id10'],
];
function(making $array in to $tree)
$tree = [];
function buildTree (array $infos, int $parent_Id = null): array
{
$branch = [];
foreach ($infos as $info)
if($info['parent_id'] === $parent_Id){
$children = buildTree($infos , $info['id']);
if ($children){
$info['children'] = $children;
}
$branch[] = $info;
}
return $branch;
}
foreach ($array as $info){
if($info['parent_id']=== 0){
$tree[] = [
'id' => $info['id'],
'name' => $info['name'],
'children' => buildTree($array , $info['id']),
];
}
}
print_r($tree);
any explanation would be appreciated.
Result of this code can be found here: http://sandbox.onlinephpfunctions.com/code/38a091db5ace63900fa0bf69ddde17412118513c
function flatMergeArray(array $array, int $parentId = 0, array &$result = []): array
{
$subResult = [];
foreach ($array as $key => $sub) {
$parentId = $array['parent_id'] ?? 0;
if (is_array($sub)) {
flatMergeArray($sub, $parentId, $result);
} else {
$subResult[$key] = $sub;
}
}
if (!empty($subResult)) {
if (!isset($subResult['parent_id'])) {
$subResult['parent_id'] = 0;
}
$result[] = $subResult;
}
return $result;
}
function flatTree(array $tree): array
{
$array = flatMergeArray($tree);
usort($array, static function (array $node1, array $node2) {
return ($node1['id'] < $node2['id']) ? -1 : 1;
});
return array_values($array);
}
$tree = [
[
"id" => 1,
"name" => "id1",
"children" => [
[
"id" => 2,
"parent_id" => 1,
"name" => "id2",
"children" => [
[
"id" => 5,
"parent_id" => 2,
"name" => "id5"
]
]
],
[
"id" => 3,
"parent_id" => 1,
"name" => "id3",
"children" => [
[
"id" => 6,
"parent_id" => 3,
"name" => "id6"
],
[
"id" => 8,
"parent_id" => 3,
"name" => "id8"
]
]
]
]
],
[
"id" => 4,
"name" => "id4",
"children" => [
[
"id" => 9,
"parent_id" => 4,
"name" => "id9",
"children" => [
[
"id" => 10,
"parent_id" => 9,
"name" => "id10"
]
]
]
]
],
[
"id" => 7,
"name" => "id7",
"children" => [
]
]
];
$array = flatTree($tree);
print_r($array);

How to remove any sub array and keep only two top levels of a multidimensional array?

I need to modify an array with subarrays and keep only the top two arrays (array -> results - x) and remove any subarray below. For example array "location" & "syncState" should be removed.
Original array:
$device_array = [
"totalCount" => "3",
"results" => [
[
"id" => "2",
"serialNumber" => "DX",
"location" => ["id" => "5", "locationName" => "US"]
],
[
"id" => "4",
"serialNumber" => "DM",
"syncState" => ["id" => "7", "locationName" => "DE"]
],
[
"id" => "5",
"serialNumber" => "C0"
]
]
];
The array should look like this:
Array
(
[totalCount] => 3
[results] => Array
(
[0] => Array
(
[id] => 2
[serialNumber] => DX
)
[1] => Array
(
[id] => 4
[serialNumber] => DM
)
[2] => Array
(
[id] => 5
[serialNumber] => C0
)
)
)
I'm trying to loop through the arrays (sub arrays included) but I can't remove all of the subarrays that sit under $device_array['results'][x].
foreach ($device_array as $key => $value) {
if(is_array($value)) {
unset($device_array['results'][0]['location']);
}
}
You can just loop the results subarray directly and write a custom filter which will modify each entry by reference. Any of the associative elements that hold array type data will be filtered out.
Code: (Demo)
$array = [
"totalCount" => "3",
"results" => [
[
"id" => "2",
"serialNumber" => "DX",
"location" => ["id" => "5", "locationName" => "US"]
],
[
"id" => "4",
"serialNumber" => "DM",
"syncState" => ["id" => "7", "locationName" => "DE"]
],
[
"id" => "5",
"serialNumber" => "C0"
]
]
];
foreach ($array['results'] as &$entry) {
$entry = array_filter($entry, 'is_scalar');
}
var_export($array);
Output:
array (
'totalCount' => '3',
'results' =>
array (
0 =>
array (
'id' => '2',
'serialNumber' => 'DX',
),
1 =>
array (
'id' => '4',
'serialNumber' => 'DM',
),
2 =>
array (
'id' => '5',
'serialNumber' => 'C0',
),
),
)
Or completely functional style: (Demo)
$array['results'] = array_map(
function($entry) {
return array_filter($entry, 'is_scalar');
},
$array['results']
);
var_export($array);
This is how you obtain the output, but I am not so sure if this is what you need in your case
<?php
$array = [
'total' => 2,
'result' => [
[
'id' => 1,
'serialNumber' => 'DX',
'location' => ['id'=>1, 'locationName'=>'US']
],
[
'id' => 2 ,
'serialNumber' => 'DO',
'syncState' => ['id'=>7, 'locationName'=>'DE']
]
]
];
foreach( $array['result'] as $key => $value ){
foreach($value as $key2=>$subarray){
if(is_array($subarray)){
unset($value[$key2]);
}
}
$array['result'][$key] = $value;
}
print_r($array);

How to restructure an array so that a sub array key becomes array key

First time posting here and really need some help. Relatively new to php I have an array that I'd like to restructure. I have subjects at top level with students in a sub array. I'd like to restructure so that Students are at the top level with subjects in a sub array.
$startingArray = [
[ "subject" => "Physics",
"student" => [
["id" => "00003", "Name" => "Peter", "email" => "peter#schooool.com",],
["id" => "00004", "Name" => "Mary", "email" => "mary#schooool.com",],
["id" => "00005", "Name" => "Jane", "email" => "jane#schooool.com",],
]
],
[ "subject" => "Chemistry",
"student" => [
["id" => "00003", "Name" => "Peter", "email" => "peter#schooool.com",],
["id" => "00004", "Name" => "Mary", "email" => "mary#schooool.com",],
["id" => "00005", "Name" => "Jane", "email" => "jane#schooool.com",],
]
],
[ "subject" => "Mathematics",
"student" => [
["id" => "00003", "Name" => "Peter", "email" => "peter#schooool.com",],
["id" => "00006", "Name" => "Fred", "email" => "fred#schooool.com",],
["id" => "00007", "Name" => "Wilma", "email" => "wilma#schooool.com",],
]
],
[ "subject" => "Biology",
"student" => [
["id" => "00004", "Name" => "Mary", "email" => "mary#schooool.com",],
["id" => "00006", "Name" => "Fred", "email" => "fred#schooool.com",],
["id" => "00008", "Name" => "Alison", "email" => "alison#schooool.com",],
]
]
];
I want my new array to be like this;
$endingArray = [
"students" => [
[ "id" => "00003",
"Name" => "Peter",
"email" => "peter#schooool.com",
"subjects" => [ "Physics", "Chemistry", "Mathematics", ],
],
[ "id" => "00004",
"Name" => "Mary",
"email" => "mary#schooool.com",
"subjects" => [ "Physics", "Chemistry", "Biology", ],
],
[ "id" => "00005",
"Name" => "Jane",
"email" => "jane#schooool.com",
"subjects" => [ "Physics", "Chemistry", ],
],
[ "id" => "00006",
"Name" => "Fred",
"email" => "fred#schooool.com",
"subjects" => [ "Mathematics", "Biology", ],
],
[ "id" => "00007",
"Name" => "Wilma",
"email" => "wilma#schooool.com",
"subjects" => [ "Mathematics", "Biology", ],
],
[ "id" => "00008",
"Name" => "Alison",
"email" => "alison#schooool.com",
"subjects" => [ "Physics", "Biology", ],
],
],
];
I'm trying a 2 stage process. First is to create the new students array without the subjects. This works fine.
Then I'm trying to append the subjects but I know my logic is wrong and the code I have just creates a new row for each student and each subject.
foreach ( $startingArray as $row ) {
$students = $row['student'];
foreach ($students as $student) {
if (!in_array($student, $studentsArray)) {
$studentsArray[] = $student;
}
}
}
the second step just produces garbage
$s1 = $student['id'];
foreach ($startingArray as $row) {
$subject = $row['subject'];
$students = $row['student'];
foreach ($students as $s2) {
if ($s2['id]'] = $s1) {
$student['subjects'] = $subject;
array_push($studentsArray, $student);
}
}
}
}
Any help appreciated!
Here what you can do:
$newArray = [];
foreach ($startingArray as $item) {
foreach ($item['student'] as $student) {
if (empty($newArray[$student['id']])) {
$student['subjects'] = [];
$newArray[$student['id']] = $student;
}
$newArray[$student['id']]['subjects'][] = $item['subject'];
}
}
Sample fiddle here.
Case you need to maintain a sequential id like your example do this
$newArray = [];
foreach ($startingArray as $item) {
foreach ($item["student"] as $student) {
$filter = array_filter($newArray, function ($d) use ($student) {
return ($d["id"] == $student["id"]);
});
if (!$filter) {
$student["subjects"][] = $item['subject'];
$newArray[] = $student;
} else {
$newArray[key($filter)]["subjects"][] = $item["subject"];
}
}
}
$finalArray = [
'students' => $newArray
];
The final result will be
Array
(
[students] => Array
(
[0] => Array
(
[id] => 00003
[Name] => Peter
[email] => peter#schooool.com
[subjects] => Array
(
[0] => Physics
[1] => Chemistry
[2] => Mathematics
)
)
[1] => Array
(
[id] => 00004
[Name] => Mary
[email] => mary#schooool.com
[subjects] => Array
(
[0] => Physics
[1] => Chemistry
[2] => Biology
)
)
[2] => Array
(
[id] => 00005
[Name] => Jane
[email] => jane#schooool.com
[subjects] => Array
(
[0] => Physics
[1] => Chemistry
)
)
[3] => Array
(
[id] => 00006
[Name] => Fred
[email] => fred#schooool.com
[subjects] => Array
(
[0] => Mathematics
[1] => Biology
)
)
[4] => Array
(
[id] => 00007
[Name] => Wilma
[email] => wilma#schooool.com
[subjects] => Array
(
[0] => Mathematics
)
)
[5] => Array
(
[id] => 00008
[Name] => Alison
[email] => alison#schooool.com
[subjects] => Array
(
[0] => Biology
)
)
)
)

How to get certain values from multidimensional arrays?

Here's the data I am working with right now:
$city = [
[
"name" => "Dhaka",
"areas" => ["d1", "d2", "d3"]
],
[
"name" => "Chittagong",
"areas" => ["c1", "c2", "c3"]
],
[
"name" => "Sylhet",
"areas" => ["s1", "s2", "s3"]
],
[
"name" => "Barisal",
"areas" => ["b1", "b2", "b3"]
],
[
"name" => "Khulna",
"areas" => ["k1", "k2", "k3"]
],
[
"name" => "Rajshahi",
"areas" => ["r1", "r2", "r3"]
],
];
I would like to get a list of data associated with only "name" key.
I would also like to show the data associated with "area" key once the user go for the corresponding "name".
It would be helpful if there were any suggestion on how to better store this data for frequent usage in code.
As long as the names are unique you can do this simple trick:
Example 1
$city = [
[
"name" => "Dhaka",
"areas" => ["d1", "d2", "d3"]
],
[
"name" => "Chittagong",
"areas" => ["c1", "c2", "c3"]
],
[
"name" => "Sylhet",
"areas" => ["s1", "s2", "s3"]
],
[
"name" => "Barisal",
"areas" => ["b1", "b2", "b3"]
],
[
"name" => "Khulna",
"areas" => ["k1", "k2", "k3"]
],
[
"name" => "Rajshahi",
"areas" => ["r1", "r2", "r3"]
],
];
$names = array_column($city, null, 'name');
print_r($names);
Output
Array
(
[Dhaka] => Array
(
[name] => Dhaka
[areas] => Array
(
[0] => d1
[1] => d2
[2] => d3
)
)
[Chittagong] => Array
(
[name] => Chittagong
[areas] => Array
(
[0] => c1
[1] => c2
[2] => c3
)
)
[Sylhet] => Array
(
[name] => Sylhet
[areas] => Array
(
[0] => s1
[1] => s2
[2] => s3
)
)
[Barisal] => Array
(
[name] => Barisal
[areas] => Array
(
[0] => b1
[1] => b2
[2] => b3
)
)
[Khulna] => Array
(
[name] => Khulna
[areas] => Array
(
[0] => k1
[1] => k2
[2] => k3
)
)
[Rajshahi] => Array
(
[name] => Rajshahi
[areas] => Array
(
[0] => r1
[1] => r2
[2] => r3
)
)
)
Now you can lookup by name
print_r($city['Chittagong']['areas']); //["c1", "c2", "c3"]
If the names are not guaranteed to be unique, you'll have to build them using foreach, like this:
Example 2
$city = [
[
"name" => "Dhaka",
"areas" => ["d1", "d2", "d3"]
],
[
"name" => "Chittagong",
"areas" => ["c1", "c2", "c3"]
],
[ /*--- ADDED to show duplication ---- */
"name" => "Chittagong",
"areas" => ["x1", "x2", "x3"]
],
[
"name" => "Sylhet",
"areas" => ["s1", "s2", "s3"]
],
[
"name" => "Barisal",
"areas" => ["b1", "b2", "b3"]
],
[
"name" => "Khulna",
"areas" => ["k1", "k2", "k3"]
],
[
"name" => "Rajshahi",
"areas" => ["r1", "r2", "r3"]
],
];
$output = [];
foreach($city as $k=>$v){
$k = $v['name'];
if(!isset($output[$k])) $output[$k] = []; //initialize
$output[$k][] = $v;
}
print_r($output);
Which will give you something like this:
Array
(
[Dhaka] => Array
(
[0] => Array
(
[name] => Dhaka
[areas] => Array
(
[0] => d1
[1] => d2
[2] => d3
)
)
)
[Chittagong] => Array
(
[0] => Array
(
[name] => Chittagong
[areas] => Array
(
[0] => c1
[1] => c2
[2] => c3
)
)
[1] => Array
(
[name] => Chittagong
[areas] => Array
(
[0] => x1
[1] => x2
[2] => x3
)
)
)
[Sylhet] => Array( ... )
As you can see this adds an extra level in to contain the multiple occurrences. Of course you could just combine the area when duplicate (in the foreach). But that is up to you.
Here is a quick example of that (same data as above):
Example 3
$output = [];
foreach($city as $k=>$v){
$k = $v['name'];
if(!isset($output[$k])) $output[$k] = []; //initialize
$output[$k] = array_merge($output[$k], $v['areas']); //merge the areas
}
print_r($output);
Output
Array
(
[Dhaka] => Array
(
[0] => d1
[1] => d2
[2] => d3
)
[Chittagong] => Array
(
[0] => c1
[1] => c2
[2] => c3
[3] => x1
[4] => x2
[5] => x3
)
....
)
If it was me, I would go with the last one, just because of the simplicity it will have working with it later.
PS. if your pulling data out of a Database with PDO, you can use $stmt->fetchAll(PDO::FETCH_GROUP) which will give you something like the second example automatically. The only caveat here is that the name column is the first one selected in the Query, which is the column it will group on.
Cheers.
If you're just trying to loop through the list of cities and get the names you can just use a foreach loop. If you need something beyond this try to define your question a little more.
foreach ($city as $c) {
echo $c["name"];
}

Sort an associative array by group with random group ordering

I have an associative array key/values indicating a group. I'd like to shuffle the array so that the groups are in a random order but so that the items in the groups are shuffled only within their group. In other words, I want to take something like this:
[
[
"name" => "Buffy",
"group" => 1
],
[
"name" => "Willow",
"group" => 1
],
[
"name" => "Xander",
"group" => 2
],
[
"name" => "Giles",
"group" => 2
],
[
"name" => "Tara",
"group" => 3
],
[
"name" => "Angel",
"group" => 3
],
[
"name" => "Spike",
"group" => 3
]
]
And return something a bit more like this:
[
[
"name" => "Spike",
"group" => 3
]
[
"name" => "Angel",
"group" => 3
],
[
"name" => "Tara",
"group" => 3
],
[
"name" => "Willow",
"group" => 1
],
[
"name" => "Buffy",
"group" => 1
],
[
"name" => "Xander",
"group" => 2
],
[
"name" => "Giles",
"group" => 2
],
]
I realise this is probably possible with two or three sorts, but it would be great if this could be done with a single usort.
Basically, my solution shuffles the input array, temporarily restructures the input array to gather subarrays with the same group value, then returns the data to its original structure.
Code: (Demo)
shuffle($data); // randomize all subarrays
foreach ($data as $set) {
$grouped[$set['group']][] = $set; // merge subarrays on group value
}
$output = [];
foreach($grouped as $group) {
array_push($output, ...$group); // return to original array structure
}
var_export($output);
*Note that ... (splat operator) allows array_push() to store all subarrays (within each group) individually to generate the original structure.
Possible Output:
array (
0 =>
array (
'name' => 'Xander',
'group' => 2,
),
1 =>
array (
'name' => 'Giles',
'group' => 2,
),
2 =>
array (
'name' => 'Willow',
'group' => 1,
),
3 =>
array (
'name' => 'Buffy',
'group' => 1,
),
4 =>
array (
'name' => 'Spike',
'group' => 3,
),
5 =>
array (
'name' => 'Tara',
'group' => 3,
),
6 =>
array (
'name' => 'Angel',
'group' => 3,
),
)
Try...
$groups = [];
foreach (array_unique(array_column($myar, 'group')) as $k) $groups[$k] = rand();
foreach (array_keys($myar) as $k) $myar[$k]['rnd'] = rand();
usort($myar, function($a, $b) use ($groups) {
if ($gdif = $groups[$b['group']] - $groups[$a['group']]) return $gdif;
return $b['rnd'] - $a['rnd'];
});
foreach (array_keys($myar) as $k) unset($myar[$k]['rnd']);
print_r($myar);
Run with your data, this is one result...
Array
(
[0] => Array
(
[name] => Buffy
[group] => 1
)
[1] => Array
(
[name] => Willow
[group] => 1
)
[2] => Array
(
[name] => Angel
[group] => 3
)
[3] => Array
(
[name] => Tara
[group] => 3
)
[4] => Array
(
[name] => Spike
[group] => 3
)
[5] => Array
(
[name] => Giles
[group] => 2
)
[6] => Array
(
[name] => Xander
[group] => 2
)
)

Categories