Not sure what issue was with first pastebin code, here is another attempt.
I am connecting to Vimeo Live API, in doing so the response is huge > 500kb in total - I have an example with only one object here -> there are over 20 it returns. I have a better idea of what Im doing in JS than PHP, but returning the huge array or json to the browser doesn't seem like a good idea and its use of repeated ajax calls isn't good either. So this question is two fold, both in theory and practice. Is this a good design and how do I filter the result in PHP and only send what I need back to browser.
Here is the design, or at least what I think is best:
page loads, sends ajax request to PHP script
PHP script connects to API and gets response in an array (example of one object)
Search through the array for 'metadata->connections->live_video' for one that has an associated array containing [status] => streaming'
If one (there will only be one at a time) is found, return that whole object and that object only, not the entire array.
At this time I do not have a complete understanding of how this data should be returned or formatted for ease of sifting through. Ive tried using json_encode on the array, which gets nicely formatted JSON but I can't iterate through it and can only get single objects like data[0]->metadata->connections->live_video. Ive tried json_encode, then json_decode and Im back to a similar array structure of what is originally sent.
However, in the browser I am able to return the whole array and in the success function of the ajax call sift through it via JS like so:
let live_stream = json.data.filter(function(value, key) {
let connection = value.metadata.connections['live_video'];
return connection && connection.status === 'streaming';
});
I know this isn't the right way, I know I need to sift through the array, find the object / key Im looking for and only return that. Any advice is appreciated, once I get this figured out, I can apply it in a range of ways for this project.
The closest I can get in PHP is:
function live_event() {
global xxx;
$lib = xxx;
$response = xxx;
$body = $response['body'];
header('Content-Type: application/json');
$jsonstr = json_encode($body);
$json = json_decode($jsonstr);
foreach ($json->data as $item) {
if ($item->uri == "/live_events/2354796") {
echo"one";
}
}
}
and this:
function live_event() {
$global xxx;
$lib = xxx;
$response = xxx;
$body = $response['body'];
header('Content-Type: application/json');
$jsonstr = json_encode($body);
$json = json_decode($jsonstr,true);
$results = array_filter($json['data'], function($item) {
return $item['metadata']['connections']['live_video']['status'] == "streaming";
});
var_dump($results);
}
last one gets me this error "Warning: Trying to access array offset on value of type null in /var/www/vhosts/mysite.com/httpdocs/SSI/Vimeo.php on line 31" is there something similar to optional chaining in PHP? if its null I don't want it to log an error.
This at least output "one" as there is only one object with [uri]=>"/live_events/2354796". I can't get it to return that entire object or search one more nested array deeper.
There are a few things that come to mind.
OBJECTS:
If you're using PHP 8 you could use the safe access operator
function live_event() {
//...
$results = []
foreach ($json->data as $item) {
if($item?->metadata?->connections?->live_video?->status == 'streaming'){
$results[] = $item;
}
}
return $results;
}
ARRAYS:
For lower versions of PHP it's better to work with arrays when dealing with keys that may or may not exists.
Generally speaking whatever fetch library you're working with will allow you set the output to either array or object. If Object is your only option then yes doing the old json_decode(json_encode($data), true) is the way to go.
checking first isset(). Assuming that's it's desired to filter out results without that key.
function live_event() {
//...
$results = array_filter($json['data'], function($item) {
if(!isset($item['metadata']['connections']['live_video']['status']))
return false;
return $item['metadata']['connections']['live_video']['status'] == "streaming";
});
header('Content-Type: application/json');
echo json_encode([
"status" => true,
"data" => $results
]);
}
or you can always just use the age old trick of suppressing the error with the # symbol. TBH i'm not sure where the # symbol would go to suppress the error, perhaps in front of the filter function definition.
function live_event() {
//...
$results = array_filter($json['data'], function($item) {
return #$item['metadata']['connections']['live_video']['status'] == "streaming";
});
return $results;
}
I currently have this large JSON file: hastebin
But just want the titles of the posts.
I've tried this...
$json = $page;
$o = json_decode($json, true);
echo($json);
$titles = $o["*"]["*"]["*"]["*"]["title"];
var_dump($titles);
But it isn't working - it's returning NULL! Sometimes it just doesn't return anything.
If anyone is wondering, yes this is from Reddit.
This should do it:
$titles = array_map(function($post) {
return $post['data']['title'];
}, $o['data']['children']);
I'm not sure what you expected using "x" indices, but you should probably read about arrays.
PHP can't use wildcards like * in array keys. Whatever string you use to reference the key, it's going to try to find a key with that exact string. So what you tried can't work because there aren't any * keys.
You can get it by iterating all the levels, or iterating the outer level and referring to the proper nested key. But if you're just looking for all instances of 'title' a recursive method may be an easier way to get them.
array_walk_recursive($o, function($value, $key) use (&$titles) {
if ($key == 'title') $result[] = $value;
});
var_dump($titles);
This will get any value of 'title' regardless of its depth in the array, so if that's not what you want, then you'll need to iterate it and specifically reference the proper ones.
It's very hard to deal directly with such a long JSON document. The returned result from the page is not a valid JSON. It contains some HTML tags, but if you take the posts data and insert it in a file you can do the following according to the structure of your JSON (You can find your JSON in an external link here):
<?php
header("Content-Type:application/json");
$posts=file_get_contents('json.php');
//decode your JSON STRING
$posts=json_decode($posts,true);
//create a title variable to store your titles
$titles=array();
foreach($posts['data']['children'] as $child)
{
array_push($titles,$child['data']['title']);
}
echo json_encode($titles);
?>
You can even use this approach using a URL but ensure that it will return a valid JSON with no html
I'm building a shopping cart and using a cookie to store the cart contents in a JSON object.
On each page, using Javascript, I need to retrieve the cookie, parse the JSON and iterate over each row, to display the described product in the basket summary.
I decided not to use keys in the array, since if I have a record of the designation of each position, why do I need to store it in the cookie. I thought that was a smart idea, but now all my searching turns up are suggestions to use the keys.
This is a sample of the JSON:
{
"9999.9999":["CentOS6",2,"0.5",150,"23.90"],
"0002.0004":["Support5","","3",5,"12.99"],
"9999.9999":["UbuntuServer12.04LTS",1,"1",220,"42.60"]
}
I was expecting to be able to access the 'price' for example (which is in the last field of each row) of the 2nd record, like so:
basket = JSON.parse(basket);
price = basket[1][4];
That doesn't seem to work.
There are really two parts to this question.
How to cherry pick a value directly from the basket?
How to iterate through it, allowing me to operate on each row in turn?
In case you're wondering about the first field. That is the SKU of the product. The reason there are two "9999.9999" is because that is a reserved number, indicating that the product was a 'custom' product (doesn't refer directly to a catalogue item).
UPDATE
Based on #Samer's answer below, I have updated the code to use arrays, as follows:
The JSON now looks like this:
[
["9999.9999","CentOS6",2,"0.5",150,"23.90"],
["0002.0004","Support5","","3",5,"12.99"],
["9999.9999","UbuntuServer12.04LTS",1,"1",220,"42.60"]
]
I'm now attempting to access it from the cookie as follows:
var basket = readCookie('basket');
basket = JSON.parse(basket);
alert( 'Price of item 2 =' + basket[1][5] );
Only, instead of alerting, 'Price of item 2 = 12.99' I get 'Price of item 2 = undefined'.
I'm wondering what I've done wrong?
UPDATE 2
Still having trouble with this. Maybe I should explain how we're getting the data into the cookie.
The array on the cookie can be updated on the server using PHP (when adding custom items) or client-side using Javascript when a catalogue item is added.
Currently, I'm concentrating on items added server side. I'm using the following code to add the cookie:
<?
extract($_POST, EXTR_SKIP);
// Get contents of existing basket (if any) minus last ']'
// so that it's ready to be added to.
if (isset($_COOKIE['basket'])) {
$basket = json_decode($_COOKIE['basket']);
$chars = strlen($basket)-1;
//echo "<pre>".var_dump($basket)."</pre>";
$cookieVal = substr($basket, 0, $chars);
$cookieVal .= ",
[\"9999.9999\",\"$sltOS\",$vcpuPoints,\"".$ramPoints."\",$storagePoints,\"".$baseServerCostMonthUSD."\"]]";
$cookieVal = json_encode($cookieVal);
/*
* Sample format
*
[["9999.9999","CentOS6",2,"0.5",150,"23.90"],
["0002.0004","Support5","","3",5,"12.99"],
["9999.9999","UbuntuServer12.04LTS",1,"1",220,"42.60"]]
*
*/
} else {
$cookieVal = json_encode("[[\"9999.9999\",\"$sltOS\",$vcpuPoints,\"".$ramPoints."\",$storagePoints,\"".$baseServerCostMonthUSD."\"]]");
}
$exp = time()+3600; // sets expiry to 1 hour;
setcookie ( 'basket' , $cookieVal, $exp, '/' );
Then client-side for reading the cookie, I have this, which is called when the page is loaded:
function initBasket() {
var basket = readCookie('basket');
if (isJSON(basket)) {
// We'll populate the basket
basket = JSON.parse(basket);
alert(basket[1][5]);
} else {
$('#sList').html('Your basket is empty.');
return;
}
}
UPDATE 3
Finally got it working. Thanks for your help.
Maybe the code can help others, so I've included the final code below:
The PHP:
if (isset($_COOKIE['basket'])) {
$cookieVal = json_decode($_COOKIE['basket']);
$cookieVal[] = array
(
"9999.9999",
$sltOS,
$vcpuPoints,
$ramPoints,
$storagePoints,
$baseServerCostMonthUSD
);
$cookieVal = json_encode($cookieVal);
} else {
$cookieArr[] = array
(
"9999.9999",
$sltOS,
$vcpuPoints,
$ramPoints,
$storagePoints,
$baseServerCostMonthUSD
);
$cookieVal = json_encode($cookieArr);
}
// Save VPS choice in basket cookie
$exp = time()+3600; // sets expiry to 1 hour;
setcookie ( 'basket' , $cookieVal, $exp, '/' );
The Javascript:
function initBasket() {
var basket = readCookie('basket');
if (isJSON(basket)) {
// We'll populate the basket
basket = JSON.parse(basket);
alert(basket[1][5]);
} else {
$('#sList').html('Your basket is empty.');
return;
}
}
If the JSON has no keys then it's an array, simply build your data using an array instead of key/value pairs.
var data = [
['CentOS', ''],
['Another Product', ...],
];
UPDATE:
So now based on your new answer, it looks like you're trying to JSON.parse the actual array. JSON.parse usually takes in a string value which has the array and then parses it into an actual array.
To see what I mean take your data array and run it through JSON.stringify and you will see the output, that same output you can then run it through JSON.parse
The problem is in PHP: You json_encode your array twice.
Here you manually encoded it once:
$cookieVal .= ",
[\"9999.9999\",\"$sltOS\",$vcpuPoints,\"".$ramPoints."\",$storagePoints,\"".$baseServerCostMonthUSD."\"]]";
Then here, you do it again:
$cookieVal = json_encode($cookieVal);
So as a result you get a string when you parse json it in javascript.
Obviously, second basket[1][4] gives you an undefined value, since basket is a string and basket[1] is a character.
It helps to use firebug or other debugging utility to take a look what data you get at every step.
So. Simply build an array of arrays in PHP and then json_encode it (once) and your js should work.
{
"9999.9999":["CentOS6",2,"0.5",150,"23.90"],
"0002.0004":["Support5","","3",5,"12.99"],
"9999.9999":["UbuntuServer12.04LTS",1,"1",220,"42.60"]
}
Mind the curly-brackets. This indicates that this is an object.
You cannot iterate through an object by numeric index.
Also mind the duplicated key "9999.9999", the first row will be overwritten by the third row.
You may try to use a for-in loop for looping through an object but this is not recommended.
var basket = JSON.parse(basket);
for(var key in basket)
{
var price = basket[key][4];
// do something with the price.
}
Anyways, this JSON object has structural problem. You should consider a better structure, an plain-old array should be good enough.
I have the following in php:
$query = mysql_query($sql);
$rows = mysql_num_rows($query);
$data['course_num']=$rows;
$data['course_data'] = array();
while ($fetch = mysql_fetch_assoc($query) )
{
$courseData = array(
'course_name'=>$fetch['course_name'],
'training_field'=>$fetch['training_field'],
'speciality_field'=>$fetch['speciality_field'],
'language'=>$fetch['language'],
'description'=>$fetch['description'],
'type'=>$fetch['type'],
);
array_push($data['course_data'],$courseData);
}
echo json_encode($data);
when I receive the result of this script in jquery (using post)
I log it using :
console.log(data['course_data']);
and the output is :
[Object { course_name="Introduction to C++", training_field="Engineering" , speciality_field="Software", more...}]
But I can't seem to figure out how to access the elements.
I tried
data['course_data'].course_name
data['course_data']['course_name']
Nothing worked. Any ideas
When you array_push($data['course_data'],$courseData); you are actually putting $courseData at $data['course_data'][0] and therefore you would access it in JavaScript as data['course_data'][0]['course_name'].
If you only intend to have one result, instead of array_push($data['course_data'],$courseData); you should just specify $data['course_data'] = $courseData. Otherwise, you should iterate over data['course_data'] like so:
for (i in data['course_data']) {
console.log(data['course_data'][i]['course_name']);
}
You should specify the index in the first array for instance
data['course_data'][0]['course_name'];
you could make it better if you had defined the first array just as variable not a variable within an array
$data['course_data'][0]['course_name']
should do the trick. If not please send the output of var_dump($data)
Assuming the PHP code is correct, you will receive a JSON data like:
{
"course_num":34,
"course_data":[
{
"course_name":"name_value",
....
},
....etc (other object based on SQL result)
]
}
So, if you want to access to the total number of result:
data.course_num
If you want to access to the first element of the list of result:
data.course_data[0]
If you want to access to the name of the first element of the list of result:
data.course_data[0].course_name
or
data.course_data[0]['course_name']
use jquery's parseJSON method to get all the goodies out of the json object...
http://api.jquery.com/jQuery.parseJSON/
I'm attempting to use the VirusTotal API to return the virus scan for a certain file. I've been able to get my current PHP code to upload the file to VirusTotal as well as get the results in an array. My question is, how would I get the [detected] value from every virus scanner under the scans object? My PHP code is below as well as a link to the output of the array.
require_once('VirusTotalApiV2.php');
/* Initialize the VirusTotalApi class. */
$api = new VirusTotalAPIV2('');
if (!isset($_GET["hash"])) {
$result = $api->scanFile('file.exe');
$scanId = $api->getScanID($result);
$api->displayResult($result);
} else {
$report = $api->getFileReport($_GET["hash"]);
$api->displayResult($report);
print($api->getSubmissionDate($report) . '<br>');
print($api->getReportPermalink($report, TRUE) . '<br>');
}
http://joshua-ferrara.com/viruscan/VirusTotalApiV2Test.php?hash=46faf763525b75b408c927866923f4ac82a953d67efe80173848921609dc7a44
You would probably have to iterate each object under scans in a for loop and either store them in yet another array or echo them out of just want to print. For example
$detectedA = {nProtect, CAT-QuickHeal, McAfee...nth};
$datContainer = array();
for ($i = 0; i < $api.length ; i++){
//Either store in an array
$api->$scans->detectedA(i)-> detected = $datContainer(i);
//Or echo it all
echo $api->$scans->detectedA(i)->detected;
return true;
}
Granted that's probably not the way you access that object but the idea still applies.
This description of stdClass demonstrates how you can not only store arbitrary tuples of data in an object without defining a class, but also how you can cast an arbitrary object as an array - which would then let you iterate over the sub-objects in your case.
Or, if I've misunderstood your question and you're actually getting an array back from the VirusTotal API and not a stdClass instance, then all you need to do is loop.
Store the scans into an array (of scans), then just loop through the array as usual.
foreach($scans as $scan) echo $scan->detected;
Or, if I'm not quite understanding the question right, is detected an array (or an object)?
Edit because of your comments -
The object returned holds an object of objects, so you need to do some casting.
foreach((array)$scans as $scanObj) {
$scan=(array)$scanObj;
foreach($scan as $anti) {
print $anti->detected; } }