Rewrite json in loop - php

I have an array, which i wrote like a table for more reability.
[{
"id": "1",
"title": "boune",
"value": "3"
}, {
"id": "2",
"title": "check",
"value": "4"
}, {
"id": "3",
"title": "boune",
"value": "5"
}]
As the result of what i want to see is this json, where 'value' of identical 'titles' united inside [] brackets. I am very newbie in php. I undestand that i need for loop to sort query result, but can`t heck...Cant even put my mind to it...
[{
"id":"1",
"title": "boune",
"value": [3, 5]
}]

<?php
$json = '[{"id":"1","title":"boune","value":"3"},{"id":"2","title":"check","value":"4"},{"id":"3","title":"boune","value":"5"}]';
$json_data = json_decode($json,true);
function accumulateValuesByTitle($json_data){
$hash = [];
foreach($json_data as $each_record){
if(isset($hash[$each_record['title']])){
$hash[$each_record['title']]['value'][] = $each_record['value'];
if($hash[$each_record['title']]['id'] > $each_record['id']){
$hash[$each_record['title']]['id'] = $each_record['id'];
}
}else{
$hash[$each_record['title']] = $each_record;
$hash[$each_record['title']]['value'] = [$hash[$each_record['title']]['value']];
}
}
return array_values($hash);
}
$modified_data = accumulateValuesByTitle($json_data);
echo json_encode($modified_data);

Related

php execution changes array format

My php file, receives two variables $addNodeProperty and $addNodeValue and adds those to an array. Unfortunately the format is changing during this process and I can´t figure out why.
The array, before the php execution:
"properties": [
{
"property": "CPU",
"value": "4"
},
{
"property": "RAM",
"value": "16 GB"
},
{
"property": "HDD",
"value": "2 TB"
}
]
The array, after the php execution. You will notice the object numbers in front of the first three entries. Those I need to remove, it should look like the array before the execution with the added object:
"properties": {
"0": {
"property": "CPU",
"value": "4"
},
"1": {
"property": "RAM",
"value": "16 GB"
},
"2": {
"property": "HDD",
"value": "2 TB"
},
{
"property": "Neue Eigenschaft",
"value": "Neuer Wert"
}
}
The php I am using:
<?php
header("Access-Control-Allow-Origin: *");
$nodeId = ($_POST['nodeId']);
$addNodeProperty = ($_POST['addNodeProperty']);
$addNodeValue = ($_POST['addNodeValue']);
$json = file_get_contents("../data/data.json");
$data = json_decode($json, true);
$nodes = $data['nodes'];
$nodeIdInArray = array_search($nodeId, array_column($nodes, 'id'));
$nodes[$nodeIdInArray]['properties']['property'] = $addNodeProperty;
$nodes[$nodeIdInArray]['properties']['value'] = $addNodeValue;
$nodes = array_values($nodes);
$data['nodes'] = $nodes;
$json = json_encode($data);
file_put_contents("../data/data.json", $json);
?>
Simple Arrays can not holds keys, that is why it is converting it to associative array.
If you still need like the 1st code
"properties": [
{
"property": "CPU",
"value": "4"
},
{
"property": "RAM",
"value": "16 GB"
},
{
"property": "HDD",
"value": "2 TB"
}
]
then you should use something like this:
... ['properties'][] = ["property"=> "Neue Eigenschaft", "value"=> "Neuer Wert"]

Combine $request->request and $request->files arrays

Im posting a multipart with text and files and trying to pass data to form, but these data are separated, so I want to combine them.
$request->request->all()
$request->files->all()
$form = $this->createForm(ParkingType::class, new Parking());
$form->submit($INeedToPassTheCombinedArray);
if ($form->isValid()) {
return $form->getData();
}
Both arrays have the same structure.
For example:
$request->request->all()
{
"name": "Test",
"taxId": "asd12",
"nationality": "england",
"parkings": [{
"total": 4,
"capacity": 928,
"places": [{
"total": 123,
"name": "test",
"address": "test"
},
{
"total": 123,
"name": "test",
"address": "test"
}
]
}]
}
$request->files->all()
{
"parkings": [{
"generalInfo": "File.pdf",
"places": [{
"logo": "File1.png"
},
{
"logo": "File2.png"
}
]
}]
}
I want to combine then in one single array, getting this:
{
"name": "Test",
"taxId": "asd12",
"nationality": "england",
"parkings": [{
"total": 4,
"capacity": 928,
"generalInfo": "File.pdf",
"places": [{
"total": 123,
"name": "test",
"address": "test",
"logo": "File1.png"
},
{
"total": 123,
"name": "test",
"address": "test",
"logo": "File2.png"
}
]
}]
}
I tried using array_merge, but the result is a single array which contain 2 arrays. It is not adding the data of one array in the respective position of the other array.
I want to know if there is some method for do this automatically and elegant.
Hope this will solve your problem
$data1 = json_decode($data,true);// first post array
$data2 = json_decode($file,true);//second file array
foreach($data1['parkings'] as $key=>&$val){ // Loop though one array
$val2 = $data2['parkings'][$key]; // Get the values from the other array
$val += $val2; // combine 'em
foreach($val['places'] as $k=>&$v){
$val3 = $val2['places'][$k]; // Get the values from the other array
$v += $val3; // combine 'em
}
}
echo json_encode($data1);
{
"name": "Test",
"taxId": "asd12",
"nationality": "england",
"parkings": [
{
"total": 4,
"capacity": 928,
"places": [
{
"total": 123,
"name": "test",
"address": "test",
"logo": "File1.png"
},
{
"total": 123,
"name": "test",
"address": "test",
"logo": "File2.png"
}
],
"generalInfo": "File.pdf"
}
]
}

PHP json_encode string key as array

i write a api for my games to get achievements and so on. i load the data from a webserver into unity c# over a www request. i need a array from php which contain achievements and more data. the problem is, the result is this
[
{"ID":"1",
"gameID":"1",
"name":"achv1",
"neededvalue":"50",
"player_achievements":{
"ID":"8",
"achievementID":"1",
"playerID":"9",
"value":"",
"completed":""
}
},
{"ID":"2",
"gameID": "1",
"name":"achv2",
"neededvalue":"100",
"player_achievements":{
"ID":"9",
"achievementID":"2",
"playerID":"9",
"value":"","completed":""
}
}
]
the player_achievements is a child array of the head array and i need the square_brackets around the player_achievements [] because untity c# cannot convert it to an object. i search hours for finding a solution but nobody explain how. i found this link but this is not a option for me. i want the string keys and not numbers. give it a way to use the string keys as array and not as object ?
i need it like so:
[
{ "ID":"1",
"gameID":"1",
"name":"achv1",
"neededvalue":"50",
"player_achievements":[
{ "ID":"8",
"achievementID":"1",
"playerID":"9",
"value":"",
"completed":""
}
]
},
{
"ID":"2",
"gameID":"1",
"name":"achv2",
"neededvalue":"100",
"player_achievements":[
{ "ID":"9",
"achievementID":"2",
"playerID":"9",
"value":"",
"completed":""
}
]
}
]
If I am reading your question correctly, you need to make the player_achievements element an array containing the original value of that element.
<?php
$json = <<<END
[
{"ID":"1",
"gameID":"1",
"name":"achv1",
"neededvalue":"50",
"player_achievements":{
"ID":"8",
"achievementID":"1",
"playerID":"9",
"value":"",
"completed":""
}
},
{"ID":"2",
"gameID": "1",
"name":"achv2",
"neededvalue":"100",
"player_achievements":{
"ID":"9",
"achievementID":"2",
"playerID":"9",
"value":"","completed":""
}
}
]
END;
$data = json_decode($json, true);
for($i=0;$i<sizeof($data);$i++)
{
$data[$i]['player_achievements'] = [$data[$i]['player_achievements']];
}
echo json_encode($data);
This produces a structure like the one you say you need.
[
{
"ID": "1",
"gameID": "1",
"name": "achv1",
"neededvalue": "50",
"player_achievements": [
{
"ID": "8",
"achievementID": "1",
"playerID": "9",
"value": "",
"completed": ""
}
]
},
{
"ID": "2",
"gameID": "1",
"name": "achv2",
"neededvalue": "100",
"player_achievements": [
{
"ID": "9",
"achievementID": "2",
"playerID": "9",
"value": "",
"completed": ""
}
]
}
]
I found an answer, I add a zero before the child element as key of array.

Combine Two Multidimensional Arrays in PHP With The Same ID

I want to add values from one array to another that are both potentially multidimensional when they have the same ID. Hard to explain so I added example.
arr1 => new structure, without full data
arr2 => old structure, with full data
Examples if you'd like to help out:
// arr1 (the correct structure/order, without the full data)
[{
"id": "24",
"children": [{
"id": "21",
"children": [{
"id": "15"
}]
}]
}]
// arr2 (full data, not in any specific order, may be nested)
[{
"id": "24",
"name": " x",
"time": "0",
"status": "0"
}, {
"id": "21",
"children": [{
"id": "15",
"name": "x",
"time": "0",
"status": "0"
}],
"name": "x",
"time": "0",
"status": "0"
}]
// arr3 (desired output for this example)
[{
"id": "24",
"children": [{
"id": "21",
"children": [{
"id": "15",
"name": "x",
"time": "0",
"status": "0"
}],
"name": "x",
"time": "0",
"status": "0"
}],
"name": " x",
"time": "0",
"status": "0"
}]
I tried this:
function merge($arr1, $arr2) {
foreach($arr1 as $key => $value){
foreach($arr2 as $value2) {
if($value['id'] === $value2['id']){
$arr1[$key]['name'] = $value2['name'];
$arr1[$key]['time'] = $value2['time'];
$arr1[$key]['status'] = $value2['status'];
if (is_array($value)) {
$arr1[$key]['children'] = merge($arr1, $arr2);
}
}
}
}
return $arr1;
}
to combine them, but I can't figure out how to handle the nesting correctly. I have tried a lot of other things as well like using array_merge_recursive() but it doesn't work because I want to merge based on ID value. Any help on getting me on track would be awesome thanks.
Current output for example:
[{
"id": "24",
"children": [{
"id": "21",
"children": [{
"id": "15"
}]
}],
"name": " x",
"time": "0",
"status": "0"
}]
Desired output for example:
[{
"id": "24",
"children": [{
"id": "21",
"children": [{
"id": "15",
"name": "x",
"time": "0",
"status": "0"
}],
"name": "x",
"time": "0",
"status": "0"
}],
"name": " x",
"time": "0",
"status": "0"
}]
Edit: How about this?
$detailsClean = [];
foreach($array2 as $item) {
$detailsClean = removeDepth($item, $detailsClean);
}
foreach($array1 as $itemKey => $item) {
$array1[$itemKey] = addDetails($item, $detailsClean);
}
function removeDepth($array, $result) {
$id = $array['id'];
if (!empty($array['children'])) {
foreach($array['children'] as $child) {
$result = removeDepth($child, $result);
}
unset($array['children']);
}
$result[$id] = $array;
return $result;
}
function addDetails($array, $details) {
$id = $array['id'];
if (isset($details[$id])) {
$array = array_merge($array, $details[$id]);
if (!empty($array['children'])) {
foreach($array['children'] as $childKey => $child) {
$array['children'][$childKey] = addDetails($child, $details);
}
}
}
return $array;
}
$array1 is updated with the final result.
Here is an example with the data from your unedited post: http://phpio.net/s/7z09
EDIT - I think I understand the problem now
From the example you gave, I realised the problem - your old array has all the data, but not the parent-child relationships, so you want to populate the new array (with the correct relationships) with the data form the old array. The problem here is that the merge function would have to fetch data from an arbitrary generation in the old array to populate the new array. This could mean a lot of looping.
So I think the solution is first to loop through the old data and flatten it - just have an associative array where the key is the "id" value. Then go through the new array and populate it from the flattened, "lookup" array. Does that make sense? In any case, you'd have two functions:
$lookUp = array();
//recursive function to flatten $arr2 into $lookUp array.
function indexOriginal($arr, &$lookUp) {
foreach($arr as $value) {
$lookUp[$value["id"]] = $value;
if (isset($value['children'])) {
unset($lookUp[$value["id"]]['children']);
indexOriginal($value['children'], $lookUp);
}
}
}
indexOriginal($arr2, $lookUp);
Then you populate the new array:
function fillInNew($arr, $lookUp) {
$return = array();
foreach($arr as $value) {
$newEntry = $lookUp[$value["id"]];
if (isset($value['children'])) $newEntry['children'] = fillInNew($value['children'], $lookUp);
$return[] = $newEntry;
}
return $return;
}
$newArr = fillInNew($arr1, $lookUp);
And $newArr should be what you're looking for
OLD USELESS STUFF FROM BEFORE:
This part of your code is weird to me:
if (is_array($value)) {
$arr1[$key]['children'] = merge($arr1, $arr2);
}
Obviously I may be completely confused, but don't you just need to put this?
if (isset($value2['children'])) $arr1[$key]['children'] = array_merge($arr1[$key]['children'], $value2['children']);
EDIT: I added array_merge because I saw that the 'children' array in the incomplete version could also need merging.
EDIT 2: now I've noticed that children can have further children (makes sense, I guess), which is why you had the correct idea of using the function recursively. You just seem to have passed in the wrong arrays - you want to pass in $arr1[$key]['children'] (as the incomplete array) and $value2['children'] (as the complete array)
function merge($arr1, $arr2) {
foreach($arr1 as $key => $value){
foreach($arr2 as $value2) {
if($value['id'] === $value2['id']){
$arr1[$key]['name'] = $value2['name'];
$arr1[$key]['time'] = $value2['time'];
$arr1[$key]['status'] = $value2['status'];
if (isset($value2['children'])) $arr1[$key]['children'] = merge($arr1[$key]['children'], $value2['children']);
}
}
}
return $arr1;
}

FuelPHP + JSON + Ajax

For example, when I use Model_Trabalhos::query()->related('categoria'), I Get a normal JSON like this:
{
"id": "1",
"categoria_id": "2",
"empresa": "Veja",
"nome": "Veja",
"thumb_pequena": "jobs/digital/veja/thumb.jpg",
"thumb_grande": "jobs/digital/veja/thumb_grande.jpg",
"destaque": "0",
"categoria": {
"id": "2",
"titulo": "Digital"
},
"imagens": {
"1": {
"id": "1",
"url": "jobs/digital/veja/1.png",
"legenda": "",
"job_id": "1"
},
"2": {
"id": "2",
"url": "jobs/digital/veja/2.png",
"legenda": "",
"job_id": "1"
}
}
}
instead, I wanted to receive back this:
[
{
"id": "3",
"categoria_id": "2",
"empresa": "Valor Econômico",
"nome": "Novo Site",
"thumb_pequena": "jobs/digital/valor-economico/thumb.jpg",
"thumb_grande": "jobs/digital/valor-economico/thumb_grande.jpg",
"destaque": "1",
"categoria": {
"id": "2",
"titulo": "Digital"
},
"imagens": [
{
"id": "3",
"url": "jobs/digital/valor-economico/1.png",
"legenda": "",
"job_id": "3"
}
]
}
]
You see? In the second case, it's wrapped in an array, and I wanted to know if there's a function in FuelPHP native that wrap the content to be ordered.
I'm in trouble... I'm using FuelPHP + ORM to get all my records from a database and generating a JSON to use with JavaScript and Ajax, but in Chrome, the JSON is not following the order by defined, is there any workaround for this problem?
If you're wanting your information in a certain way you could follow that query with a foreach loop that would add them to an array of arrays (translated to an array of JSON objects) once converted to JSON.
$query = Model_Trabalhos::query()->related('categoria')
$categories = array();
foreach ($query as $category) {
$categories[] = array(
'id' => $category->id,
...
);
}
return $categories;
It's an old question, but i had the same problem now and colud resolve like the answer that i posted in https://stackoverflow.com/a/34242106/5670195.
In case it is a function that converts into simple array, the objects returned as the relationship of ORM.

Categories