hi im bulding a site with php that use a json api and i need to echo the values of an multidimensional array
"troopsLevels": [
{
"value": 5,
"globalID": 4000000
},
{
"value": 5,
"globalID": 4000001
},
{
"value": 4,
"globalID": 4000002
},
this is a example of my json file what i need is to show the value "value" knowing depending of the globalID
but not sure how to do it
i was thinking something like
$troop_lvl = $data['troopsLevels'];
if($troop_lvl['globalID'] == 4000000){echo $troop_lvl['value']}
but of curse this will not work as i dont specify the item [0]..[2]
but that actually thats what i need to avoid using [0] to select specific array i need to read all and only show the ['value'] when i give the globalid
i really hope yo can understand me english is not my mother language
thanks a lot for you help
You need to use foreach loop
foreach ($troop_lvl as $key=>$value) {
if($value['globalID'] == 4000000) {
echo $value['value'];
}
}
Use foreach
foreach ($troop_lvl as $key=>$value) {
if($value['globalID'] == 4000000) {
echo $troop_lvl['value'];
}
}
See below:
<?php
$arr = array("test" => array("value" => 1, "value2" => 2), "test2" => array("value" => 21, "value2" => 22));
$encode_arr = json_encode($arr);
$decode_arr = json_decode($encode_arr);
//print_r($decode_arr);
foreach ($decode_arr as $key => $value) {
if($value->value2==2)
echo $value->value;
}
?>
The output will be 1.
This should work for you,
$a = '{"troopsLevels": [
{
"value": 5,
"globalID": 4000000
},
{
"value": 5,
"globalID": 4000001
},
{
"value": 4,
"globalID": 4000002
}
]}';
$abc = json_decode($a);
foreach ($abc->troopsLevels as $row) {
if ($row->globalID == 4000000) {
echo $row->value;// prints value as 5 for the current input.
}
}
Related
This question already has answers here:
How to GROUP BY and SUM PHP Array? [duplicate]
(2 answers)
Closed 9 months ago.
I'm having a hard time manipulating an array of objects in PHP. I need to group the objects by id, while summing up the points.
Starting array of objects:
[
{
"id": "xx",
"points": 25
},
{
"id": "xx",
"points": 40
},
{
"id": "xy",
"points": 40
},
]
What I need:
[
{
"id": "xx",
"points": 65
},
{
"id": "xy",
"points": 40
},
]
As a frontender, I'm having a hard time with object/array manipulations in PHP. Any help would be greatly appreciated!
i hope this answer help you
first i will change objects to array and return the result to array again
$values =[
[
"id"=> "xx",
"points"=> 25
],
[
"id"=> "xx",
"points"=> 40
],
[
"id"=> "xy",
"points"=> 40
],
];
$res = array();
foreach($values as $vals){
if(array_key_exists($vals['id'],$res)){
$res[$vals['id']]['points'] += $vals['points'];
$res[$vals['id']]['id'] = $vals['id'];
}
else{
$res[$vals['id']] = $vals;
}
}
$result = array();
foreach ($res as $item){
$result[] = (object) $item;
}
output enter image description here
Parse JSON as Object
Aggregate Data
Put back as JSON
$json = <<<'_JSON'
[
{
"id": "xx",
"points": 25
},
{
"id": "xx",
"points": 40
},
{
"id": "xy",
"points": 40
}
]
_JSON;
$aggregate = [];
foreach(json_decode($json) as $data) {
if(!isset($aggregate[$data->id])) $aggregate[$data->id] = 0;
$aggregate[$data->id] += $data->points;
}
$output = [];
foreach($aggregate as $id => $points) {
$output[] = ['id' => $id, 'points' => $points];
}
echo json_encode($output);
[{"id":"xx","points":65},{"id":"xy","points":40}]
You may use array_reduce buil-in function to do the job. Also, when looping through the object's array (the callback), you should check if the result array has the current item's ID to verify that wether you need to add the item to the result array or to make the sum of points attributes.
Here's an example:
// a dummy class just to replicate the objects with ID and points attributes
class Dummy
{
public $id;
public $points;
public function __construct($id, $points)
{
$this->id = $id;
$this->points = $points;
}
}
// the array of objects
$arr = [new Dummy('xx', 25), new Dummy('xx', 40), new Dummy('xy', 40)];
// loop through the array
$res = array_reduce($arr, function($carry, $item) {
// holds the index of the object that has the same ID on the resulting array, if it stays NULL means it should add $item to the result array, otherwise calculate the sum of points attributes
$idx = null;
// trying to find the object that has the same id as the current item
foreach($carry as $k => $v)
if($v->id == $item->id) {
$idx = $k;
break;
}
// if nothing found, add $item to the result array, otherwise sum the points attributes
$idx === null ? $carry[] = $item:$carry[$idx]->points += $item->points;
// return the result array for the next iteration
return $carry;
}, []);
This will result in something like this:
array(2) {
[0]=>
object(Dummy)#1 (2) {
["id"]=>
string(2) "xx"
["points"]=>
int(65)
}
[1]=>
object(Dummy)#3 (2) {
["id"]=>
string(2) "xy"
["points"]=>
int(40)
}
}
Hope that helps, feel free to ask for further help.
Let's use a helper variable called $map:
$map = [];
Build your map:
foreach ($input => $item) {
if (!isset($map[$item["id"]])) $map[$item["id"]] = 0;
$map[$item["id"]] += $item["points"];
}
Now let's build the output:
$output = [];
foreach ($map as $key => $value) {
$output[] = (object)["id" => $key, "points" => $value];
}
I would like to Loop throught services but I don't know the index name. They come randomly, example I got 8 and 9 but I do not know them.
"2": {
"first_name": "khalfan",
"last_name": "mussa",
"date": "2017-06-06 09:21:36",
"gender": "male",
"services": {
"8": {
"name": "See a Doctor",
"results": ""
},
"9": {
"name": "Kichocho",
"results": "FD- 73"
}
}
},
From #Alive to Die answer, I made some changes and I think this code will loop in your services no matter the index.
$array = json_decode($json, true);
foreach ($array as $values) {
foreach ($values as $keys => $value) {
if (is_array($value)) {
foreach ($value as $key => $val) {
if (is_array($val)) {
foreach ($val as $k => $v) {
echo $k . ":" . $v . "\n";
}
}
}
}
}
}
Suppose you have json stored in $json variable.
$json = json_decode($json);
foreach($json as $entry) {
foreach($entry['services'] as $services) {
//$services['name']
//and other data here
}
}
You don't need to know the index while using foreach but you can get index from it.
The following are four available options:
<?php
$arr = ["2" => [
["first_name"=> "khalfan",
"last_name"=> "mussa",
"date"=>"2017-06-06 09:21:36",
"gender"=> "male"],
["services" =>
["8" => ["name" => "See a Doctor","results"=> ""],
"9" => ["name"=> "Kichocho","results"=> "FD- 73"]
]
]
]];
for ($i=0, $max=count($arr["2"]); $i < $max; $i++) {
if ( isset( $arr["2"][$i]["services"])) {
$a = $arr["2"][$i]["services"];
foreach($a as $e) {
echo $e["name"],"\t";
echo $e["results"],"\n";
}
}
continue;
}
See live code
The advantage here is that the code does work with a foreach as per the OP's request. But the code is involved and not as fast as it could be, owing to that if conditional.
Another solution that is faster:
<?php
$arr = ["2" => [
["first_name"=> "khalfan",
"last_name"=> "mussa",
"date"=>"2017-06-06 09:21:36",
"gender"=> "male"],
["services" =>
["8" => ["name" => "See a Doctor","results"=> ""],
"9" => ["name"=> "Kichocho","results"=> "FD- 73"]
]
]
]];
$count = count($arr["2"]);
$last = $count - 1; // b/c of zero-based indexing
foreach ($arr as $e) {
foreach($e[$last]["services"] as $a) {
echo $a["name"],"\t";
echo $a["results"],"\n";
}
}
// Or an easier solution without resorting to foreach:
array_walk_recursive($arr,function($item,$key) {
if ($key == "name") echo $item,"\t";
if ($key == "results") echo $item,"\n";
});
See live code
Whether $arr["2"] contains two elements or more as long as the last one is the "services" associate array, this foreach code works. But, this type of "array walk" can best be carried out with a built-in function designed for this very purpose, array_walk_recursive. With this function, you don't have to worry about how to construct the perfect foreach; the iteration occurs behind the scenes and all you need is to supply a callback. array_walk_recursive will drill down to the "services" element and if there is one or more associative arrays with keys of "name" and "results", then their respective values display.
The fourth possibility is one of those "why would you" situations. Why take an array and json_encode it and then json_decode it back to an array and then apply array_walk_recursive? But, the code does work:
<?php
$arr = ["2" => [
["first_name"=> "khalfan",
"last_name"=> "mussa",
"date"=>"2017-06-06 09:21:36",
"gender"=> "male"],
["services" =>
["8" => ["name" => "See a Doctor","results"=> ""],
"9" => ["name"=> "Kichocho","results"=> "FD- 73"]
]
]
]];
$result=json_decode(json_encode($arr),true);
array_walk_recursive($result, function($value,$key){
if ($key == "name" ) { echo $value,"\t";}
if ($key == "results") { echo $value,"\n";}
});
See live code
I have 3 arrays for storing posts,comments, and likes.
These are the JSON strings:
//comments JSON (stores user and comment points)
$comments='[
{
"user": "5",
"points": "12"
},
{
"user": "2",
"points": "1"
},
{
"user": "3",
"points": "1"
}
]';
//likes(stores user and likes point)
$likes='[
{
"user": "1",
"points": 7
},
{
"user": "4",
"points": 4
},
{
"user": "3",
"points": 1
}
]';
//posts (stores user and post points)
$posts='[
{
"user": "1",
"points": "6"
},
{
"user": "3",
"points": "2"
},
{
"user": "2",
"points": "1"
}
]';
I convert these JSONs into arrays like this:
$comment_array = json_decode($comments,TRUE);
$like_array = json_decode($likes,TRUE);
$post_array = json_decode($posts,TRUE);
//echo '<pre>';
//print_r($comment_array);
//print_r($like_array);
//print_r($post_array);
//echo '</pre>';
Now, I'm trying to sum these points and save the result in a new array. It's not mandatory that a user should have entries in all the three arrays. It depends on whether a user has made a comment, post or like.
function mergeArrays($filenames, $titles, $descriptions) {
$result = array();
foreach ( $filenames as $key=>$name ) {
$result[] = array( 'filename' => $name, 'title' => $titles[$key], 'descriptions' => $descriptions[ $key ] );
}
return $result;
}
The above function can merge all the three arrays.
$merged= mergeArrays($comment_array, $like_array, $post_array);
echo '<pre>';
print_r($merged);
echo '</pre>';
However, each array after merging is stored as an index element.
How can I get a result something like this:
$result='[
{
"user": "1",
"points": "13"
},
{
"user": "2",
"points": "2"
},
{
"user": "3",
"points": "4"
},
{
"user": "4",
"points": "4"
},
{
"user": "5",
"points": "12"
}
]';
Considering your three arrays, this code will get you an array with: points, votes and diferent users.
Edit: Adding additional array and printing it to get the output desired by question.
$points = 0;
$uniqueUsers = array();
$votes = 0;
$users = 0;
$result = array();
//Comments
if (!empty($comment_array)) {
foreach ($comment_array as $item) {
if (!in_array($item['user'], $uniqueUsers)) {
array_push($uniqueUsers, $item['user']);
$result[$item['user']] = 0;
}
$votes ++;
$result[$item['user']] += $item['points'];
}
}
// Likes
if (!empty($like_array)) {
foreach ($like_array as $item) {
if (!in_array($item['user'], $uniqueUsers)) {
array_push($uniqueUsers, $item['user']);
$result[$item['user']] = 0;
}
$votes ++;
$result[$item['user']] += $item['points'];
}
}
// Posts
if (!empty($post_array)) {
foreach ($post_array as $item) {
if (!in_array($item['user'], $uniqueUsers)) {
array_push($uniqueUsers, $item['user']);
$result[$item['user']] = 0;
}
$votes ++;
$result[$item['user']] += $item['points'];
}
}
foreach ($result as $idUser=>$points) {
echo "\n";
echo "\n" . 'User: ' . $idUser;
echo "\n" . 'Points: ' . $points;
}
$results = array('users'=> count($uniqueUsers), 'votes'=>$votes, 'points'=> $points);
//print_r($results);
The solution using array_column, array_walk_recursive and array_values functions:
...
$comments = array_column($comment_array, 'points', 'user');
$likes = array_column($like_array, 'points', 'user');
$posts = array_column($post_array, 'points', 'user');
$list = [$comments, $likes, $posts];
$result = [];
array_walk_recursive($list, function($v, $k) use(&$result){
if (key_exists($k, $result)){
$result[$k]['points'] += $v;
} else {
$result[$k] = ['user' => $k, 'points' => $v];
}
});
$result = array_values($result);
print_r($result);
The output:
Array
(
[0] => Array
(
[user] => 5
[points] => 12
)
[1] => Array
(
[user] => 2
[points] => 2
)
[2] => Array
(
[user] => 3
[points] => 4
)
[3] => Array
(
[user] => 1
[points] => 13
)
[4] => Array
(
[user] => 4
[points] => 4
)
)
Do the following to get one array with summed points:
$collections = array(
'comments' => json_decode($comments,TRUE),
'likes' => json_decode($likes,TRUE);,
'posts' => json_decode($posts,TRUE),
);
$newArray = array();
foreach ($collections as $collection) {
foreach ($collection as $user) {
$newArray[$user->user] += $user->points;
}
}
There are two important points to make if you want to learn the "best" way to handle these types of operations.
Don't use iterated in_array() calls when isset() can be used instead. This is because isset() is much more efficient than in_array().
Use temporary keys to identify duplicate occurrences, then re-index your results when finished -- usually with array_values(), but this time I used array_multisort() to re-order the results AND re-index.
Code: (Demo)
$merged = array_merge(json_decode($comments, true), json_decode($likes, true), json_decode($posts, true));
$result = [];
foreach ($merged as $entry) {
if (!isset($result[$entry['user']])) {
$result[$entry['user']] = $entry;
} else {
$result[$entry['user']]['points'] += $entry['points'];
}
}
array_multisort(array_column($result, 'user'), $result);
// usort($result, function($a, $b) { return $a['user'] <=> $b['user']; });
// array_multisort() will outperform `usort()` in this case.
echo json_encode($result);
Output:
[{"user":"1","points":13},{"user":"2","points":2},{"user":"3","points":4},{"user":"4","points":4},{"user":"5","points":"12"}]
Decode each array and merge them together into a multi-dimensional array.
Iterate each subarray and determine if it is the first occurrence of the user. If so, retain the entire subarray. If not, only increase the points tally within that subarray.
When the loop is finished, sort by user ascending.
This is clean, direct, and readable.
Here's what I want to do in my php array to be exact json format below:
JSON
{
"suggestions": [
{ "value": "Alex - alex#email.com", "data": {"id": 1, "name": Alex } },
{ "value": "John - john#email.com", "data": {"id": 2, "name": John } },
{ "value": "Diaz - diaz#email.com", "data": {"id": 3, "name": Diaz } }
]
}
Query result in my php array:
array(
0 => array('id'=>'1' 'email'=>'alex#email.com', 'name'=>'Alex'),
1 => array('id'=>'2' 'email'=>'john#email.com', 'name'=>'John'),
2 => array('id'=>'3' 'email'=>'diaz#email.com', 'name'=>'Diaz')
);
Do you have any idea how will you make my php array to that JSON format way?
You can simply use json_encode(); function for that.
json_encode($array);
This should help you for your JSON format
foreach($query as $key => $val){
$json[$key]['value'] = $val['name']." - ".$val['email'];
$json[$key]['data']["id"] = $val['id'];
$json[$key]['data']["name"] = $val['name'];
}
echo json_encode($json);
foreach ($your_array as $key => $val) {
foreach ($val as $k => $v) {
if ($v == 'email') {
//get the value of 'email' key in 'value'
$newArr['suggestions']['value'] = current($v);
}
else {
//if value is not email push it in 'data' key
$newArr['suggestions']['data'] = $v;
}
}
}
//lastly encode the required array
echo json_encode($newArr);
Here's my JSON code:
{
"query": {
"count": 2,
"created": "2013-04-03T09:47:03Z",
"lang": "en-US",
"results": {
"yctCategories": {
"yctCategory": {
"score": "0.504762",
"content": "Computing"
}
},
"entities": {
"entity": [
{
"score": "0.902",
"text": {
"end": "19",
"endchar": "19",
"start": "0",
"startchar": "0",
"content": "Computer programming"
},
"wiki_url": "http://en.wikipedia.com/wiki/Computer_programming"
},
{
"score": "0.575",
"text": {
"end": "51",
"endchar": "51",
"start": "41",
"startchar": "41",
"content": "programming"
}
}
]
}
}
}
}
and below is my PHP code
$json_o = json_decode($json,true);
echo "Json result:</br>";
echo $json; // json
echo "</br></br>";
echo "Value result:</br>";
$result = array();
//$entity = $json_o['query']['results']['entities']['entity'];
foreach ($json_o['query']['results']['entities']['entity'] as $theentity)
foreach ($theentity['text'] as $thetext){
$result[] = $thetext['content'];
}
print_r($result);
My expectation is to get the value of content in entity, which is "Computer programming" and "programming".
I already searching around, but still have found the solution yet.
The result of my PHP code is:
Array ( [0] => 1 [1] => 1 [2] => 0 [3] => 0 [4] => C [5] => 5 [6] => 5 [7] => 4 [8] => 4 [9] => p )
Use this loop
foreach ($json_o['query']['results']['entities']['entity'] as $theentity)
{
$result[] = $theentity['text']['content'];
}
http://codepad.viper-7.com/tFxh1w
Output Array ( [0] => Computer programming [1] => programming )
Change your foreach to:
$result = array();
foreach ($json_o['query']['results']['entities']['entity'] as $theentity) {
$result[] = $theentity['text']['content'];
}
print_r($result);
$theentity['text'] is an array of keys => value. You can just access key content instead of looping through all of the entries.
Another way you could do it (though it is a poor choice) is:
foreach($theentity['text'] as $key => $value) {
if( 'content' === $key ) {
$result[] = $value;
}
}
I provide this second example to demonstrate why the original code did not work.
Update
To access other properties like the yctCategories just do something similar
$categories = array();
foreach ($json_o['query']['results']['yctCategories'] as $yctCategory) {
$categories[] = $yctCategory['content'];
}
print_r($categories);
remove the second foreach and replace it with $result[] = $theentity['text']['content'];
using something like http://jsonlint.com/ might make it easier for you to see how the json is structured. alternatively just var_dump (or print_r) the output of your json_decode.
Use simple code:
$array = $json_o['query']['results']['entities']['entity'];
foreach($array as $v){
echo $v['text']['content'];
}