Deep Associative Array to adjacent mysql table - php

Been fighting the whole night. Giving up. I have an adjacent table in mysql:
id, parentid,name,design,path,sort
The depth is maximum four and using mysql query, I print out the results to UL list successfully. From there, items are added, sorted and edited as well as removed. Then when button is clicked, I send the result back to php. The data been sent is JSON and it does get recieved.
json_decode() gives the following sample:
Array ( [0] => Array ( [cls] => [path] => # [id] => 1 [name] =>BLOCKA ) [1] => Array ( [cls] => [path] => # [id] => 2 [name] => BLOCKB [children] => Array ( [0] => Array ( [cls] => [path] => # [id] => 3 [name] => CLASSB1 [children] => Array ( [0] => Array ( [cls] => [path] => # [id] => 7 [name] => CLASSB12 ) ) ) [1] => Array ( [cls] => [path] => # [id] => 4 [name] => CLASSSB13 [children] => Array ( [0] => Array ( [cls] => [path] => # [id] => 5 [name] => CLASSB4 ) [1] => Array ( [cls] => [path] => # [id] => 6 [name] => CLASSB5 ) ) ) ) ) )
Graphically:
BLOCKA
BLOCKB
CLASSB1
CLASSB3
...
I am using jquery.nested
Now my problem is looping through the array, getting id of the parent then add child.
The closest I came with is
function dissect($blocks) {
if (!is_array($blocks)) {
echo $blocks;
return;
}
foreach($blocks as $block) {
dissect($block);
}
}
It does process each element but not in the way I want. Sorry for my broken english...any help would be appreciated.

First iterate through blocks getting the parent, if children exists in parent block, loop through the children.
There might be other better way to implement this, you can try below code:
$blocks = array (
"0" => array (
"cls" => "",
"path" => array(
"id" => 1,
"name" =>"BLOCKA",
)
),
"1" => array (
"cls" => "",
"path" => array(
"id" => 2,
"name" => "BLOCKB" ,
"children" => array (
"0" => array (
"cls" => "",
"path" => array(
"id" => 3,
"name" => "CLASSB1" ,
"children" => array (
"0" => array (
"cls" => "",
"path" => array(
"id" => 7,
"name" => "CLASSB12" ,
),
),
),
),
),
"1" => array (
"cls" => "",
"path" => array(
"id" => 4,
"name" => "CLASSSB13" ,
"children" => array (
"0" => array (
"cls" => "",
"path" => array(
"id" => 5,
"name" => "CLASSB4" ,
),
),
"1" => array (
"cls" => "",
"path" => array(
"id" => 6,
"name" => "CLASSB5",
),
),
),
),
),
),
),
),
) ;
echo "<pre>";
/*loop through blocks*/
foreach ($blocks as $key => $block) {
echo $block['path']['name'].'<br/>'; /* echo parent*/
if (isset($block['path']['children'])) {
loopChildren($block['path']['children']); /* children loop*/
}
}
/*Loop through childrens*/
function loopChildren($childrens, $prefix = '-')
{
foreach ($childrens as $key => $child) {
getChild($child, $prefix);
}
}
/*Get the child and loop sub-children if exist*/
function getChild($child, $prefix='-')
{
echo $prefix. $child['path']['name'].'<br/>'; /*echo child*/
if (isset($child['path']['children'])) {
$prefix .= '-';
loopChildren($child['path']['children'], $prefix); /* sub-children loop*/
}
}
echo "</pre>";
The output:
BLOCKA
BLOCKB
-CLASSB1
--CLASSB12
-CLASSSB13
--CLASSB4
--CLASSB5

thanks for your tip. It guided me to an answer that worked for me. I ended up using two functions. The error was "index out of bound"...here is what I did now...with calls to the mysql table:
$response = json_decode($_POST['s'], true); // decoding received JSON to array
if(is_array($response)){
//start saving now
$order=1;
foreach ($response as $key => $block) {
//0 is for blocks: no parent id needed
$parentid=$this->Blocks_model->insertblock($block['name'],$block['cls'],0,$block['path'],$order);
if (isset($block['children'])) {
$this->childblocks($parentid,$block['children']);
}
$order++;
}
}
private function childblocks($parentid,$e){
$order=1;
foreach ($e as $key => $block) {
$parentid=$this->Blocks_model->insertblock($block['name'],$block['cls'],0,$block['path'],$order);
if (isset($block['children'])) {
$this->childblocks($parentid,$block['children']);
}
$order++;
}
}

Related

How do I get values from this array? PHP

Very much new to PHP and completely stuck because of #attributes when trying to pick values out of an array. I have previously converted an xml file into a associative array.
print_r(array_keys($newArray));
Prints:
Array ( [0] => #attributes [1] => rate )
print_r ($newArray);
Prints:
Array (
[#attributes] => Array (
[base] => GBP
[ts] => 1572881347 )
[rate] => Array (
[0] => Array (
[#attributes] => Array (
[code] => AED
[rate] => 4.739532203531
[live] => 0
)
)
[1] => Array (
[#attributes] => Array (
[code] => AFN
[rate] => 100.80144337913
[live] => 0
)
)
[2] => Array (
[#attributes] => Array (
[code] => ALL
[rate] => 142.29721877018
[live] => 0
)
)
[3] => Array (
[#attributes] => Array (
[code] => AMD
[rate] => 614.98298701028
[live] => 0
)
)
How would I specify and print the last value?
[3] => Array ( [#attributes] => Array ( [code] => AMD [rate] => 614.98298701028 [live] => 0.
With the goal to output something like: AMD, 614.98298701028, 0
Thanks
More generally, if you'd want to look-up a currency in your array, you could use following recursive function:
$code = 'AMD'; // set the curncy you want to lookup
forex($code, $newArray); // invoke the recursive function
// output:
//code : AMD
//rate : 614.98298701028
function forex(string $code = '', array $arr = []): void
{
foreach ($arr as $key => $value) {
if (is_array($value) && $key !== '#attributes') {
forex($code, $value);
} else {
if (isset($value['code']) && $value['code'] == $code) {
echo 'code : ' . $value['code'];
echo '<br />';
echo 'rate : ' . $value['rate'];
echo '<br />';
}
}
}
}
working demo
Assuming that your original array is something like this:
$a = array(
'#attributes' => array(
'base' => 'GBP',
'ts' => 1572881347),
'rate' => array(
0 => array(
'#attributes' => array(
'code' => 'AED',
'rate' => 4.739532203531,
'live' => 0,
),
),
1 => array(
'#attributes' => array(
'code' => 'AFN',
'rate' => 100.80144337913,
'live' => 0,
),
),
2 => array(
'#attributes' => array(
'code' => 'ALL',
'rate' => 142.29721877018,
'live' => 0,
),
),
3 => array(
'#attributes' => array(
'code' => 'AMD',
'rate' => 614.98298701028,
'live' => 0,
),
)));
then you can get what you want with this:
$last_rate = sizeof($a['rate']) - 1;
foreach ($a['rate'][$last_rate]['#attributes'] as $key => $value) {
echo "$value ";
}
Which will output:
AMD 614.98298701028 0
If your array will always contain the array values under rate, you can retrieve the last element of the rate array by using end($newArray['rate']).
To output a CSV style string you can simply use implode(', ', $last['#attributes']) or another desired method, such as foreach, to display the values from the last element.
Example: https://3v4l.org/FNuuZ
if ($last = end($newArray['rate'])) {
echo implode(', ', $last['#attributes']);
}
Result:
AMD, 614.98298701028, 0

how to build nested array from other nested array php

I have array where each element is array of sql columns.
One element of MAIN array looks like this:
Array(
[type] => water
[id] => KK
[animalName] => "josip"
[key] => 123
[key2] => 2
[alive] => true
[name] => "Lilly"
[key] => 1
[big] => false
)
now i need to build nested array which looks like this:
array(
[type] => water
[id] => KK
["animals"] => array(
[animalName] => "josip"
[key] => 123
[key2] => 1.5
[alive] => true
["babies" => array(
[name] => "jimmy"
[key] => 1
[big] => false
)
)
as long as type == type in previous element of MAIN array i need to add more animals, so
array(
[type] => water
[id] => KK
["animals"] => array(
[animalName] => "rom"
[key] => 213
[key2] => 5423
[alive] => true
["babies" => array(
[name] => "julia"
[key] => 199
[big] => false
)
)
["animals"] => array(
[key] => 123123111
[key2] => 123213
[alive] => true
[name] => "tom"
["babies" => array(
[name] => "robert"
[key] => 1123
[big] => false
)
)
i have built an algorithm but it was really complex and unoptimal so im looking for as simple as possible solution, any ideas?
the point is to get json with structure:
{
"type":"water",
"id":"KK",
"animals":[
{
"AnimalName":"crocodile",
"key":1,
"key2":1.1,
"alive":true,
"babies":[
{
"name":"jimmy",
"Key":123,
"big":false
}
]
},
{
"AnimalName":"fish",
"key":22,
"key2":1.5,
"alive":true,
"babies":[
{
"name":"lilly",
"key2":5,
"big":false
}
]
}
],
"type":"land",
"id":"LL",
"animals":[
{
"AnimalName":"lion",
"key":1,
"key2":1.1,
"alive":true,
"babies":[
{
"name":"jimmy",
"Key":123,
"big":false
}
]
},
{
"AnimalName":"dog",
"key":22,
"key2":1.5,
"alive":true,
"babies":[
{
"name":"lilly",
"key2":5,
"big":false
}
]
}
]
}
as long as type == type in previous element of main array add more animals, if type differs from previus add next element to root array with other type and add other animals.
Im sorry if its messy a little
try this, it will helpful for you..
$array = array(
'type' => 'water',
'id' => 'KK',
'animalName' => "josip",
'key' => 123,
'key2' => 2,
'alive' => 'true',
'name' => "Lilly",
'key3' => 1,
'big' => 'false'
);
$resulArray = array();
foreach ($array as $key => $value) {
if ($key == 'animalName' || $key == 'key' || $key == 'key2' || $key == 'alive') {
$resulArray['animals'][$key] = $value;
}
else if ($key == 'name' || $key == 'key3' || $key == 'big') {
$resulArray['animals']['babies'][$key] = $value;
} else {
$resulArray[$key] = $value;
}
}
// return array
echo '<pre>';
print_r($resulArray);
// return json
$resulJson = json_encode($resulArray);
echo '<pre>';
print_r($resulJson);

Sorting multidimensional array by two user defined values

I need to sort a multidimensional array by two values.
For example in the array will be 4 keys.
Array(
Array
(
[0] => 4B642D022980E5EBAA7CF4B6E1CC93769921CB42
[1] => downloading
[2] => Title
[3] => 60
)
Array
(
[0] => 4B642D022980E5EBAA7CF4B6E1CC93769921CB42
[1] => downloading
[2] => Title
[3] => 30
)
Array
(
[0] => 4B642D022980E5EBAA7CF4B6E1CC93769921CB42
[1] => paused
[2] => Title
[3] => 30
)
Array
(
[0] => 4B642D022980E5EBAA7CF4B6E1CC93769921CB42
[1] => completed
[2] => Title
[3] => 100
)
)
Is there a way I can sort the array so that it would sort the arrays with key completed first, then downloading second, then paused third and then also sort the arrays containing downloading and paused from 100 down to 0 by the 3 key?
Desired output would be
Array(
Array
(
[0] => 4B642D022980E5EBAA7CF4B6E1CC93769921CB42
[1] => completed
[2] => Title
[3] => 100
)
Array
(
[0] => 4B642D022980E5EBAA7CF4B6E1CC93769921CB42
[1] => downloading
[2] => Title
[3] => 60
)
Array
(
[0] => 4B642D022980E5EBAA7CF4B6E1CC93769921CB42
[1] => downloading
[2] => Title
[3] => 30
)
Array
(
[0] => 4B642D022980E5EBAA7CF4B6E1CC93769921CB42
[1] => paused
[2] => Title
[3] => 30
)
)
uksort is what you need.
It is a sort that lets you define you own callback function.
This callback function is then used by uksort to reorder the array.
You need to write a function that will sort an array based on two criterias.
The first one is the alphabetical order of the field at indice 1 of your array (which contains the words completed, downloading, ...) and in case of tie you would then use the field at indice 3 of your array and sort in decreasing order.
Finally, you will need to pass the function you created as a parameter to uksort.
Hope it helps ! :)
You need to reformat your array and use array_multisort. It will also make thinks more readable:
<?php $ar = Array(
Array(
"id" => "4B642D022980E5EBAA7CF4B6E1CC93769921CB42",
"status" => "completed",
"title" => "Title",
"rank" => "100",
),
Array
(
"id" => "4B642D022980E5EBAA7CF4B6E1CC93769921CB42",
"status" => "downloading",
"title" => "Title",
"rank" => "60",
),
Array
(
"id" => "4B642D022980E5EBAA7CF4B6E1CC93769921CB42",
"status" => "downloading",
"title" => "Title",
"rank" => "30",
),
Array
(
"id" => "4B642D022980E5EBAA7CF4B6E1CC93769921CB42",
"status" => "paused",
"title" => "Title",
"rank" => "30",
),
);
var_dump($ar);
foreach ($ar as $key => $row) {
$status[$key] = $row['status'];
$rank[$key] = $row['rank'];
}
array_multisort($status, SORT_ASC, $rank, SORT_DESC, $ar);
var_dump($ar);
$array = [
[
'4B642D022980E5EBAA7CF4B6E1CC93769921CB42',
'downloading',
'Title',
'60',
],
[
'4B642D022980E5EBAA7CF4B6E1CC93769921CB42',
'downloading',
'Title',
'30',
],
[
'4B642D022980E5EBAA7CF4B6E1CC93769921CB42',
'paused',
'Title',
'30',
],
[
'4B642D022980E5EBAA7CF4B6E1CC93769921CB42',
'completed',
'Title',
'100',
]
];
usort($array, function($a, $b) {
if ($a[1] == $b[1]) {
if ($a[3] == $b[3]) {
return 0;
}
return ($a[3] > $b[3]) ? -1 : 1;
}
$status = ['completed', 'downloading', 'paused'];
foreach ($status as $st) {
if ($a[1] == $st)
return -1;
if ($b[1] == $st)
return 1;
}
return 0;
});
var_dump($array);

How to loop through a multi-layer array and replace some associate values in it?

How can I loop through a multi-layer array and replace some associate values in it?
For instance, this is my array,
$items = array(
0 => array(
"id" => "1",
"title" => "parent 1",
"children" => array()
),
1 => array(
"id" => "2",
"title" => "parent 2",
"children" => array (
0 => array(
"id" => "4",
"title" => "children 1",
"granchildren" => array(
0 => array(
"id" => "7",
"title" => "granchildren 1"
),
1 => array(
"id" => "8",
"title" => "granchildren 2"
)
)
),
1 => array(
"id" => "5",
"title" => "children 2",
"granchildren" => array()
)
),
),
3 => array(
"id" => "3",
"title" => "parent 3",
"children" => array()
)
);
These are two working functions I have,
function translate ($id){
$items = array(
0 => array(
"id" => 1,
"title" => "parent 1 en"
),
1 => array(
"id" => 4,
"title" => "children 1 en"
),
2 => array(
"id" => 8,
"title" => "granchildren 2 en"
)
);
foreach($items as $item) {
if($id === $item['id'])
{
return $item['title'];
}
}
}
function looper ($items){
$new_items = array();
foreach($items as $key => $item) {
if(isset($key) && is_array($key)){
$new_items[$key] = translate($item['id']);
}else {
//looper($item);
}
}
return $new_items;
}
print_r(looper ($items));
This is the result I am after,
Array
(
[0] => Array
(
[id] => 1
[title] => parent 1 en // translated
[children] => Array
(
)
)
[1] => Array
(
[id] => 2
[title] => parent 2
[children] => Array
(
[0] => Array
(
[id] => 4
[title] => children 1 en // translated
[granchildren] => Array
(
[0] => Array
(
[id] => 7
[title] => granchildren 1
)
[1] => Array
(
[id] => 8
[title] => granchildren 2 en // translated
)
)
)
[1] => Array
(
[id] => 5
[title] => children 2
[granchildren] => Array
(
)
)
)
)
[3] => Array
(
[id] => 3
[title] => parent 3
[children] => Array
(
)
)
)
Is it possible?
Sounds like a job for array_walk or array_walk_recursive.
It will call a user-supplied function for every item in an array. You can have it modify the array by reference to achieve what you're after.

Make array unique in multidimensional array php codeigniter

I have this array
Array (
[0] => Array
(
[0] => stdClass Object
(
[id] => 226
[user_id] => 1
[name] => Eden Corner Tub by Glass - $2099
)
[1] => stdClass Object
(
[id] => 225
[user_id] => 1
[name] => Blue Quilted Leather Jacket by Minusey - $499
)
[2] => stdClass Object
(
[id] => 222
[user_id] => 1
[name] => Darling New Bathtub by Duravit - $6300
)
)
[1] => Array
(
[0] => stdClass Object
(
[id] => 226
[user_id] => 1
[name] => Eden Corner Tub by Glass - $2099
)
[1] => stdClass Object
(
[id] => 229
[user_id] => 1
[name] => Batman Tumbler Golf Cart - $50000
)
[2] => stdClass Object
(
[id] => 228
[user_id] => 1
[name] => Swirlio Frozen Fruit Dessert Maker - $60
)
) )
I have an array of products that I need to make sure are unique.
Need to make this array unique by id. These array are generated by pushing value.
I'm trying to solve this for more than a week now, but I dont get it to work. I know it should be easy...but anyway - I don't get it :D
Try this:
$array = array(
0 => array(
"name" => "test",
"id" => 4
),
1 => array(
"name" => "test2",
"id" => 152
),
2 => array(
"name" => "test2",
"id" => 152
)
);
$newArray = array();
foreach($array as $value) {
$newArray[$value['id']]['name'] = $value['name'];
$newArray[$value['id']]['id'] = $value['id'];
}
foreach($array as $key=>$inner_array)
{
foreach($array as $key_again=>$array_again)
{
if($key != $key_again)
{
if($inner_array['name'] != $array_again['name'] AND $inner_array['id'] != $array_again['id'])
{
//its okay
}
else
{
unset($array[$key]);
}
}
}
}
Not sure how the arrays are generated, but, if you can change that, you could set the array keys to the IDs directly and check if the id is already set.
Otherwise, you can do the following:
$unique = array();
foreach( $array as $values ) {
if( ! isset( $unique[$values['id']] ) ) {
$unique[$values['id']] = $values;
}
}
This will make your array unique:
$array = array(
0 => array(
"name" => "test",
"id" => 4
),
1 => array(
"name" => "test2",
"id" => 152
),
2 => array(
"name" => "test2",
"id" => 152
) );
$result = array();
$index = array();
foreach($array as $i => $elem) {
if(!isset($index[$elem['id']])) {
$result[$i] = $elem;
$index[$elem['id']] = 1;
}
}
echo var_export($result);
Output:
array (
0 =>
array (
'name' => 'test',
'id' => 4,
),
1 =>
array (
'name' => 'test2',
'id' => 152,
),
)
This will work. It could be considered more clean than a for loop, but I'm not sure about performance.
$array = [
[ "name" => "test", "id" => 4 ],
[ "name" => "test2", "id" => 152 ],
[ "name" => "test2", "id" => 152 ]
];
array_walk($array, function(&$item, $idx) use($array){
$matches = array_slice(array_keys($array, $item), 1);
if (in_array($idx, $matches)) {
$item = false;
}
});
$array = array_filter($array);
Edit Since you updated the data set to work with, you would need to flatten it 1 level:
$array = call_user_func_array('array_merge', $array);

Categories