Please correct the terminologies that I am using.
I am trying to return a json data like this:
"data": [
{
"id": 1
"name": "test"
},
{
{
"id": 2
"name": "abc"
},
{
"id": 3
"name": "zxc"
}
]
and my code is exactly this one
$data = [];
foreach($prices as $price) {
$data[]["id"] = $price->id;
$data[]["name"] = $price->name;
}
$result["data"] = $data;
the code returns the json like this:
"data": [
{
"id": 1
},
{
"name": "test"
}
{
"id": 2
},
{
"name": "abc"
}
{
"id": 3
},
{
"name": "zxc"
}
]
Sorry for the bad formatting.
Like this
foreach($prices as $price) {
$data[] = [
"id"=> $price->id,
"name" => $price->name
];
}
You are adding the items sequentially, when you need to group them in an array and then add that array as a single unit.
$i = 0;
$data = [];
foreach($prices as $price) {
$data[$i]["id"] = $price->id;
$data[$i]["name"] = $price->name;
$i++;
}
$result["data"] = $data;
The problem is that you keep appending to the array instead of appending to an object and then to the $data array.
Try like this
$data = [];
foreach($prices as $price) {
$topush = [];
$topush["id"] = $price->id;
$topush["name"] = $price->name;
$data[] = $toReturn;
}
$result["data"] = $data;
or, even shorter
$data = [];
foreach($prices as $price) {
$data[] = ['id' => $price->id, 'name' => $price->name];
}
$result["data"] = $data;
You are adding two new Elements to your output, one containing the key/value for id and the other one for name. You have to put both into one element:
$data[]["id"] = $price->id; // Add one element
$data[]["name"] = $price->name; // Add second element
// New
$data[] = ['id' => $price->id, 'name' => $price->name]; // Add both as one Element
Empty [] creates new index every time. You must specify index where you wish to insert:
$data = [];
foreach($prices as $i => $price) {
$data[$i]["id"] = $price->id;
$data[$i]["name"] = $price->name;
}
$result["data"] = $data;
You kept assigning the value to a new key you should assign the data you want bundle in one go.
$data = [];
foreach($prices as $price) {
$data[] = [
"id" => $price->id,
"name" => $price->name;
]
}
$result["data"] = $data;
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 have two tables order and orderDetail. i have multiple delivery address in order detail table based on id of order table
i want to display id from order table and deliveryAddress from order detail table.i am getting below output when i print..
but unable to display delivery_address.please anyone can suggest how i display delivery_address..
{
"responseData": {
"status": 1,
"message": "",
"result": [
{
"Order": {
"id": "677",
"detail_location_instructions": "Near Inox"
},
"OrderDetail": [
{
"order_id": "677",
"delivery_address": "Smart Club Gimnasio - Avenida Álvarez Thomas, Buenos Aires, Autonomous City of Buenos Aires, Argentina"
},
{
"order_id": "677",
"delivery_address": "Lower Fort Street, Dawes Point, New South Wales, Australia"
}
]
},
{
"Order": {
"id": "680"
},
"OrderDetail": []
},
{
"Order": {
"id": "684"
},
"OrderDetail": [
{
"order_id": "684",
"delivery_address": "Four Seasons - Posadas"
}
]
}
]
}
}
below is my code
public function getOrderlist(){
if($this->processRequest){
$err = false;
if(empty($this->requestData['id'])){
$this->responceData['message'] = "Please provide User ID";
$err = true;
}
if(!$err){
$id = trim($this->requestData['id']);
$conditions = array('Order.user_id'=>$id);
$data = $this->Order->find('all',array('conditions'=>$conditions));
if(!empty($data)){
$c = array();
foreach ($data as $key => $value) {
$c[] = array(
'Id' => $value['Order']['id'],
'deliveryAddress' => $value['OrderDetail']['delivery_address']
);
}
}
$this->responceData['result'] = $c;
$this->responceData['status'] = 1;
}
}
}
You have to put the deliveryAddress in array
$c = array();
foreach ($data as $key => $value) {
$myOrders = [
'Id'=>$value['Order']['id'],
'deliveryAddress'=>[]
];
foreach($value['OrderDetail'] as $address){
$myOrders['deliveryAddress'][] = $address['delivery_address'];
}
$c[] = $myOrders;
}
Hope this will help
can you trying below code.
foreach ($data as $key => $value) {
$c[] = array(
'Order' => array(
'id'=>$value['Order']['id'],
'detail_location_instructions' => $value['Order']['detail_location_instructions'],
),
'OrderDetail' => array(
'order_id'=>$value['Order']['id'],
'deliveryAddress' => $value['OrderDetail']['delivery_address'],
),
)
}
There is cases where you dont get the delivery address, in that case, you need to check if it exists first. use the Hash utility for that purpose.
I transformed the data to an array, in order for the class Hash to work.
public function getOrderlist(){
if($this->processRequest){
$err = false;
if(empty($this->requestData['id'])){
$this->responceData['message'] = "Please provide User ID";
$err = true;
}
if(!$err){
$id = trim($this->requestData['id']);
$conditions = array('Order.user_id'=>$id);
$data =(array) $this->Order->find('all',array('conditions'=>$conditions));
if(!empty($data)){
$c = array();
foreach ($data as $key => $value) {
$c[] = array(
'Id' => Hash::get($value, 'Order.id'),
'deliveryAddress' => current(Hash::extract($value, 'OrderDetail.{n}.delivery_address', array()))
);
}
}
$this->responceData['result'] = $c;
$this->responceData['status'] = 1;
}
}
}
Hello I have a array like this.
$myarray = Array(
[0] => Array
(
[0] => Type
[1] => Brand
)
[1] => Array
(
[0] => Car
[1] => Toyota
)
)
I want result like this.
Type = Car
Brand = Toyota
So its mean From First Array "0" Value will be echo then from second array "0" Value will be shown.
Then From First array "1" value will be shown then from second array "1" Value will be shown.
Also I don't know how many array will be comes, So its need to be dynamic.
Any help Please?
You can try something like this (now i have tested it!):
foreach($myarray[0] as $titleKey=>$title) {
echo $title . " = ";
for($i = 1;$i<count($myarray);$i++) {
echo $myarray[$i][$titleKey] . ",";
}
echo "</br>";
}
Use array_combine for this
$myarray = [
['Type', 'Brand'],
['Car', 'Toyota']
];
list($fields, $values) = $myarray;
$output = array_combine($fields, $values);
echo json_encode($output, JSON_PRETTY_PRINT);
// {
// "Type": "Car",
// "Brand": "Toyota"
// }
But as you said, it could have more values than just the Toyota, so you'd have to do it like this
$myarray = [
['Type', 'Brand'],
['Car', 'Toyota'],
['Horse', 'Seabiscuit']
];
function first ($xs) { return $xs[0]; }
function rest ($xs) { return array_slice($xs, 1); }
$output = array_map(function ($values) use ($myarray) {
return array_combine(first($myarray), $values);
}, rest($myarray));
echo json_encode($output, JSON_PRETTY_PRINT);
// [
// {
// "Type": "Car",
// "Brand": "Toyota"
// },
// {
// "Type": "Horse",
// "Brand": "Seabiscuit"
// }
// ]
Note, this final solution assumes that the first array would contain the field names and the remaining arrays would have the values
Of course this works when more fields are added, too. No changes to the code are necessary.
$myarray = [
['Type', 'Brand', 'Origin'],
['Car', 'Toyota', 'Japan'],
['Horse', 'Seabiscuit', 'Kentucky']
];
function first ($xs) { return $xs[0]; }
function rest ($xs) { return array_slice($xs, 1); }
$output = array_map(function ($values) use ($myarray) {
return array_combine(first($myarray), $values);
}, rest($myarray));
echo json_encode($output, JSON_PRETTY_PRINT);
// [
// {
// "Type": "Car",
// "Brand": "Toyota",
// "Origin": "Japan"
// },
// {
// "Type": "Horse",
// "Brand": "Seabiscuit",
// "Origin": "Kentucky"
// }
// ]
I have a multi- and variable-level json file that looks like the example at the bottom of this post. What I need to do is search for a particular value, let's say "Gap junction" and return the value for "name" for all of the higher level parents, in this example "Junction", "Plasma membrane" and "Cell". I need to do this using php and I think I need a recursive loop to traverse the array that will record the "name" value for each depth level into an array and then return this "name" array once the search term is found, but I'm struggling a bit at achieving this. Any help would be appreciated.
{
"name": "Cell",
"children": [
{
"name": "Plasma membrane",
"children": [
{
"name": "Junction",
"children": [
{"name": "Adherens junction"},
{"name": "Caveola"},
{"name": "Gap junction"},
{"name": "Lipid raft"},
{"name": "Tight junction"}
]
},
{"name": "Focal adhesion"}
]
},
{
"name": "Vesicle",
"children": [
{
"name": "Endosome",
"children": [
{"name": "Early Endosome"},
{"name": "Late Endosome"},
{"name": "Recyling Endosome"}
]
},
{ "name": "Microsome"}
]
}
]
}
EDIT
Current code as requested. The $found variable is certainly not working how I intended it too. Code is based/modified on this answer: Get Parent and Child depth level from JSON using PHP?
$jsonString = file_get_contents("./information/localization.json");
$jsonArray = json_decode($jsonString);
$currOrganelle = "Gap junction";
$parents = read_tree_recursively($jsonArray, $currOrganelle);
function read_tree_recursively($items, $searchTerm, $result = array(), $level = 0, $found = false) {
foreach($items as $child) {
if(!$found) {
$currName = $child->name;
if($currName == $searchTerm) {
$found = true;
return $result;
}
elseif(!empty($child->children)) {
$result[$level] = $currName;
$result = read_tree_recursively($child->children, $searchTerm, $result, $level + 1, $found);
if($found) return $result;
}
else {
}
}
else {
return $result;
}
}
}
Solution with RecursiveIteratorIterator and RecursiveArrayIterator classes:
// $str - is your initial json string
$decoded = json_decode($str, TRUE);
function getParentNameKeys($arr = [], $needle = "") {
$iterator = new \RecursiveIteratorIterator(new \RecursiveArrayIterator($arr));
$nameKeys = [];
foreach ($iterator as $key => $value) {
if ($value === $needle) {
$depth = $iterator->getDepth();
while ($depth--){
if ($iterator->getSubIterator($depth)->offsetExists('name')) {
$nameKeys[] = $iterator->getSubIterator($depth)->offsetGet('name');
}
}
}
}
return $nameKeys;
}
$nameKeys = getParentNameKeys($decoded, "Gap junction");
var_dump($nameKeys);
// the output:
array (size=3)
0 => string 'Junction' (length=8)
1 => string 'Plasma membrane' (length=15)
2 => string 'Cell' (length=4)
$nameKeys = getParentNameKeys($decoded, "Early Endosome");
var_dump($nameKeys);
// the output:
array (size=3)
0 => string 'Endosome' (length=8)
1 => string 'Vesicle' (length=7)
2 => string 'Cell' (length=4)
http://php.net/manual/en/class.recursiveiteratoriterator.php
I'm trying to fix a problem in my JSON API when I request a multiple result set from my database. Basically I want to store a named array, "card" for each row returned. My goal is to get the JSON to look like this:
{
"results": [
{
"card": {
"property": "value",
"property": "value",
"property": "value"
}
},
{
"card": {
"property": "value",
"property": "value",
"property": "value"
}
}
]
}
But instead it looks like this:
{
"results": [
{
"card": [
{
"property": "value",
"property": "value",
"property": "value"
},
{
"property": "value",
"property": "value",
"property": "value"
}
]
}
]
}
Below you can find my code:
// Prepare Stored Procedure Call
$dbConn = new ConnDB();
$dbConn->query("CALL " . $this->proc);
//Get Result$$$
$row = $dbConn->resultset();
foreach ($row as $key => $value) {
$this->valueArray[$key] = $value;
}
$this->data = array(
"results" => array(
array(
$this->type => $this->valueArray
),
)
);
I need to basically build a named array, "card"=>$values, for each $row, but I can't do it in the middle of an array declaration, so the best thing I could think of was this:
// Prepare Stored Procedure Call
$dbConn = new ConnDB();
$dbConn->query("CALL " . $this->proc);
//Get Result$$$
$row = $dbConn->resultset();
$jsonArray = array();
foreach ($row as $key => $value) {
array_push($jsonArray, $this->type => $this->valueArray[$key] = $value)
}
$this->data = array(
"results" => array(
array(
$jsonArray
),
)
);
But that of course gives me parse errors. Argh! A bit frustrating.
Any ideas?
YES! I figured it out.
// Prepare Stored Procedure Call
$dbConn = new ConnDB();
$dbConn->query("CALL " . $this->proc);
//Get Result$$$
$row = $dbConn->resultset();
$jsonArray = array();
foreach ($row as $key => $value) {
array_push($jsonArray, array("card" => $value));
}
$this->data = array(
"results" => $jsonArray,
);
This returns the exact format I need. I was overthinking it.
Change your code as follows
<?php
$data = array();
$json_array = array();
$test_array = array(1,2,3,4,5,6,7,8,9,10);
foreach($test_array as $t){
$json_array[]['card'] = array('property' => $t);
}
$data['results'] = $json_array;
echo json_encode($data);
?>
Result
{"results":[{"card":{"property":1}},{"card":{"property":2}},{"card":{"property":3}},{"card":{"property":4}},{"card":{"property":5}},{"card":{"property":6}},{"card":{"property":7}},{"card":{"property":8}},{"card":{"property":9}},{"card":{"property":10}}]}