Appending new data to object - php

I'm stuck trying to append new data to an stdClass object that I'm creating for an AMchart
I'm returning all the rows I want from the DB, then creating a new object and looping through the returned array, but rather than appending what I want to the end of the existing object, it just gets overwritten. PHP objects dont have an append or push method, so how do you accomplish this?
Here's what my code looks like. Am I missing something simple?
$sql = 'SELECT
count(*) as clients,
STR_TO_DATE(Appt_date, \'%m/%d/%Y\') AS date,
SUM(wait_time) as total_wait_time
FROM tb_by_client
WHERE status = #qualifier
GROUP BY Appt_date';
$rows = $db->fetchAll($sql);
$chartObject = new stdClass();
foreach($rows as $row){
$row->average = round($row->total_wait_time / $row->clients);
$chartObject->date = $row->date;
$chartObject->average = $row->average;
}
$chartArray[] = $chartObject;
return json_encode($chartArray);
So instead of getting something that looks like this
[{"date":"2018-10-01","average":12},{"date":"2018-10-02","average":-33},{"date":"2018-10-04","average":23},{"date":"2018-10-05","average":6}]
I get back just a single
[{"date":"2018-10-01","average":12}]
Because each loop overwrites the last key and value
How do you append instead?

Your problem is you overwrite the data without saving it
$chartObject = new stdClass();
foreach($rows as $row){
$row->average = round($row->total_wait_time / $row->clients);
$chartObject->date = $row->date;
$chartObject->average = $row->average;
}
$chartArray[] = $chartObject;
See on each iteration of foreach($rows as $row){ you change the data in $chartObject, but you never save in your $chartArray.
Do this instead
foreach($rows as $row){
$chartObject = new stdClass(); //new instance of stdClass, obj pass by refrence
$row->average = round($row->total_wait_time / $row->clients);
$chartObject->date = $row->date;
$chartObject->average = $row->average;
$chartArray[] = $chartObject;
}
Personally I wouldn't even bother with using an object:
foreach($rows as $row){
$average = round($row->total_wait_time / $row->clients);
$chartArray[] = ['date'=>$row->date,'average'=>$average];
}
When you JSON Encode an array with string keys, it will make it the correct Javascript Object structure. So there really is no need to keep all those objects in memory and the code is much smaller, cleaner, and easier to read.
One last thing I hinted at in the code, is that objects are pass by reference in PHP (now), and if you don't create a new instance of the object for each iteration, you will actually update all references to the object. This can be illustrated like this:
$obj = new stdClass;
$objects = [];
for($i=0;$i<3;++$i){
$obj->foo = $i;
$objects[] = $obj;
print_r($objects);
}
Output:
Array
(
[0] => stdClass Object
(
[foo] => 0
)
)
Array
(
[0] => stdClass Object
(
[foo] => 1
)
[1] => stdClass Object
(
[foo] => 1
)
)
Array
(
[0] => stdClass Object
(
[foo] => 2
)
[1] => stdClass Object
(
[foo] => 2
)
[2] => stdClass Object
(
[foo] => 2
)
)
Sanbox
Each array is a single iteration of the for loop, this is the same array with another row added after each iteration.
As you can see each copy (its not really a copy) is updated by reference in the array. Basically we have stored the same object (instance ,will call him Bob) 3 times, instead of 3 separate objects (Bob, Alice, John).
If the data you stored was the color of a persons shirt, when Bob puts on a red shirt, he has a red shirt on, but Alice and John don't.
Because of this you need to create a new instance of the object for each iteration and store that.
Hope that helps!

You can do the maths in the SQL and it cuts out the loop altogether...
$sql = 'SELECT STR_TO_DATE(Appt_date, \'%m/%d/%Y\') AS date,
round(SUM(wait_time)/count(*)) as average
FROM tb_by_client
WHERE status = #qualifier
GROUP BY Appt_date';
return json_encode($db->fetchAll($sql));

You're misunderstanding what should be in the loop and what shouldn't.
This should be fine:
$sql = 'SELECT
count(*) as clients,
STR_TO_DATE(Appt_date, \'%m/%d/%Y\') AS date,
SUM(wait_time) as total_wait_time
FROM tb_by_client
WHERE status = #qualifier
GROUP BY Appt_date';
$rows = $db->fetchAll($sql);
$chartArray = [];
foreach($rows as $row){
$row->average = round($row->total_wait_time / $row->clients);
$chartObject = new stdClass();
$chartObject->date = $row->date;
$chartObject->average = $row->average;
$chartArray[] = $chartObject;
}
return json_encode($chartArray);

Related

PHP - get value from JSON

Before i decode my JSON i get this result:
{
"1":[{"membership_id":1,"group_id":1,"user_id":1},
"2":[{"membership_id":3,"group_id":1,"user_id":2}
}
How would i specify that i want to select the one who has 'user_id' == 2 and return membership_id value?
My attempt, but i get undefined value 'user_id':
$myjson = json_decode($s_o, true);
foreach ($myjson as $key => $value){
if($value['user_id'] == $cid){
$mid = $value['membership_id'];
}
}
echo $mid;
Basically i guess i would first have to select the right object and go through it with the foreach, but here i got a bit lost in the situation.
Use Array-Functions:
$json = '{
"1":[{"membership_id":1,"group_id":1,"user_id":1}],
"2":[{"membership_id":3,"group_id":1,"user_id":2}]
}';
$array = json_decode($json, true);
$searchUserID = 2;
$filteredArray = array_filter($array, function($elem) use ($searchUserID){
return $searchUserID == $elem[0]['user_id'];
});
$mid = array_column(array_shift($filteredArray), 'membership_id')[0];
echo "Membership-ID: ".$mid;
array_filter uses a callback function that iterates over every element of the array. If the callback function returns true, that element is assigned to $filteredArray. No need for a foreach loop that way.
But the return value is the whole array element:
Array
(
[2] => Array
(
[0] => Array
(
[membership_id] => 3
[group_id] => 1
[user_id] => 2
)
)
)
So you have to extract your membership_id.
Read the following line from inside out.
First, we fetch the first entry of the array with array_shift (since we have only one entry, this will be our desired entry).
Array
(
[0] => Array
(
[membership_id] => 3
[group_id] => 1
[user_id] => 2
)
)
We pass this array on to array_column to find the entry in the encapsulated array with the column name membership_id. Since array_column again returns an array,
Array
(
[0] => 3
)
we get the (one and only) entry by adding [0] to the end of this command.
Since the last part is a little complicated, here's a torn apart version of it:
$firstEntryOfFilteredArray = array_shift($filteredArray);
$arrayWithValueOfColumnMembershipID = array_column($firstEntryOfFilteredArray, 'membership_id');
$membership_id = $arryWithValueOfColumnMembershipID[0];
These three lines are concatenated into this:
$mid = array_column(array_shift($filteredArray), 'membership_id')[0];
here's a working example: http://sandbox.onlinephpfunctions.com/code/8fe6ede71ca1e09dc68b2f3bec51743b27bf5303
I'm assuming the JSON actually looks like:
{
"1":[{"membership_id":1,"group_id":1,"user_id":1}],
"2":[{"membership_id":3,"group_id":1,"user_id":2}]
}
Each element of the object is an array for some reason. So you need to index it with $value[0] to access the object contained inside it.
$myjson = json_decode($s_o, true);
foreach ($myjson as $key => $value){
if($value[0]['user_id'] == $cid){
$mid = $value[0]['membership_id'];
break;
}
}
echo $mid;
If the arrays can contain multiple elements, you'll need nested loops.
$myjson = json_decode($s_o, true);
foreach ($myjson as $key => $value){
foreach ($value as $object) {
if($object['user_id'] == $cid){
$mid = $object['membership_id'];
break 2;
}
}
}
echo $mid;
This is a bit speculative, but I think the data is indexed by user ID. If that's the case, it makes the lookup much simpler.
After decoding with $myjson = json_decode($s_o, true);
Just find the record by ID and get the membership_id from the matching row.
$membership_id = reset($myjson['2'])['membership_id'];`
You should probably verify that that ID exists, so maybe something like:
$membership_id = isset($myjson['2']) ? reset($myjson['2'])['membership_id'] : null;
If I'm wrong and the fact that the row numbers match the user_id is just a coincidence, then never mind :)

Exclude the first result from an Array

I am currently messing around with iTunes Api and have ran into a problem with the returning process of albums track list returning the first result as the actual album data instead of the tracklist.
$loop['artist_name'] = $counted[$x]->artistName;
$loop['album_id'] = $counted[$x]->collectionId;
$loop['album_name'] = $counted[$x]->collectionName;
$loop['track_number'] = $counted[$x]->trackCount;
$loop['artwork_url'] = $counted[$x]->artworkUrl100;
$loop['copyright'] = $counted[$x]->copyright;
$loop['genre'] = $counted[$x]->primaryGenreName;
$loop['release_date'] = $counted[$x]->releaseDate;
$data_b = file_get_contents('https://itunes.apple.com/lookup?id='.$loop['album_id'].'&entity=song');
$response_ab = json_decode($data_b);
print '<pre>';
print_r($response_ab);
print '</pre>';
The above portion for print_r returns the following data.
[results] => Array
(
[0] => stdClass Object
(
[wrapperType] => collection
)
[1] => stdClass Object
(
[wrapperType] => track
)
Then continues onward down the track list, how can I remove the first [0] option from my loop? It appears this only returns the album name anyway when I am trying to get the tracklist.
I didn't test the below code however it should work.
$data_b = file_get_contents('https://itunes.apple.com/lookup?id='.$loop['album_id'].'&entity=song');
$response_ab = json_decode($data_b);
$count = $response_ab->results;
$arr = count($count);
for($a = 1; $a < $arr; $a++) {
// do some cool stuff here
}

Selecting a nested stdClass Object

Hi I was wondering if it is possible to grab:
Here is my current code:
<?php
include('php-riot-api.php');
$region = 'euw';
$grab_id = 19631093;
$instance = new riotapi($region);
$grab_dataB = $instance->getStats($grab_id);
$decode_dataB = json_decode($grab_dataB);
$grab_tier = $decode_data->{'aggregatedStats[7].Unranked[wins]'};
print_r($decode_dataB);
?>
This is my result:
http://2v2.lolnode.com/testing.php (http://pastebin.com/DrJDnuaC)
I would like to be able to get the numbered result for Unranked[wins] (which is [aggregatedStats] => stdClass Object ( ) ) [7])
You can get directly:
$grab_tier = $decode_dataB->playerStatSummaries[7]->wins;
But you won't know for sure that the 8'th key is the one you want, or ...
You can loop in your results:
$unranked = '';
foreach($decode_dataB->playerStatSummaries as $summary){
if($summary->playerStatSummaryType == 'Unranked'){
$unranked = $summary;
break;
}
}
print_r($unranked);
and get values, eg $unranked->wins
you can json_decode with 2'nd parameter true (object is transformed into array) and loop like a normal array.
$decode_dataB = json_decode($grab_dataB, true);

accessing mysql field in the simpleXML through Object / Method

I am working on generating XML file using simpleXml...I have the following code.
require_once('inc.php');
$query = $glb_connection->prepare('select * from table order by ID');
$query->execute();
$tree = $query->fetchAll();
$doc = $xml->init();
foreach($tree as $tr){
$xml_events = $doc->addChild('entr');
$xml_events->addAttribute('ID', $tr['ID']);
$xml_events->addAttribute('cmp', $tr['cmp']);
// add another child
$xml_supervisor = $xml_events->addChild('personDetail');
// instatiate class
$pro = new profile();
// passing getDetail method
$person = $pro->getDetail($tr['ID']);
// it prints all the detail of the ID as expected (using it to check if return true)
print_arr($person);
$xml_supervisor->addAttribute('firstname', $person->lastname);
$xml_supervisor->addAttribute('familyname', $person['lastname']);
}
$file = 'example.xml';
$xml->saveXML($doc,$file);
from the above code, the problem is here...I try to call the field-name from the result object person, but both way I have tried doesn't work...
$xml_supervisor->addAttribute('firstname', $person->lastname);
$xml_supervisor->addAttribute('familyname', $person['lastname']);
how can I call any key or value from generated result of person Object???
some one has help...
This is how the array generated when I call
print_arr($person);
Array
(
[0] => Array
(
[ID] => 10
[lastname] => Sara
)
)
Ohhh, Sorry to bother you every-one, I have found the problem...I don't know what is wrong with me today, any way...
Some one might need it the exact answer some-day, so here it is....
the array is Associative-array in which if we need to call ID it should be like this..
array[0][ID]...means
this should be called like this..
$xml_supervisor->addAttribute('familyname', $person[0]['lastname']);
That is it.

How to split an Array into usable data, so it can be counted and manipulated

I have this query:
SELECT carID FROM reservations WHERE startDate < '".$sqlretdate."' AND endDate > '".$sqlcoldate."' OR startDate = '".$sqlcoldate."' OR endDate = '".$sqlretdate."'"
Using a loop:
while($presentid = mysql_fetch_array($checkreservations)) {
This returns an array of data, so for example:
echo "<---space-->";
print_r($presentid['carID']);
Would display:
<---space-->11<---space-->10<---space-->2<---space-->8<---space-->9<---space-->7
This is a list of ids, I need to do something with each of them.
I can explode it:
print_r(explode(" ", $presentid['carID']));
And this would make it print like this:
Array ( [0] => 11 ) Array ( [0] => 10 ) Array ( [0] => 2 ) Array ( [0] => 8 ) Array ( [0] => 9 ) Array ( [0] => 7 )
How do I totally split each id and store it into a variable, so I can use them to do something else?
In this case each ID is unique to a car, and has a model name associated to it, so I want to use the id to find out which model name is related to it, count the number of that model name in the database, and then check to see how many of the returned ids related to that model, and therefore how many there is left. I hope that makes sense.
In your while loop, $presentid represents each row in the result set. $presentid['carID'] is not an array! It's one carID value. You do not need to use explode here at all.
while($presentid = mysql_fetch_array($checkreservations)) {
// This *is* each car ID! Do with it what you want.
$carID = $presentid['carID'];
}
$ids = array();
$count = 0;
while($presentid = mysql_fetch_array($checkreservations)) {
$ids['car_' . $count++] = $presentid['carID'];
}
extract($ids);
This will give you independent variables:
$car_0 = 11;
$car_1 = 12;
$car_2 = 2;
..etc
You can't store it into a basic variable without overwriting it, unless you want to reserve very many variables, It's best to go through the loop, store the values into an array, then you can walk trough the array once the while loop is over, unless you can just do something with them right away.
"How do I totally split each id and store it into a variable"
while($presentid = mysql_fetch_array($checkreservations))
{
$carId = $presentid['carID'];
$array[] = array('id' => $carId );
}
So you can parse through the array once It's over.

Categories