How to create a blank associative array in php - php

My php script returns data to the web client where it is processed by javaScript.
If data is found it is stored in an associative array / object. If no data is found I would like to send a blank associative array.
The only example I have seen on line is in the manual where you create an empty class and then instantiate an object from that.
Below is my code and the results it produces on the web client side
$sql = 'select job, client, project from jobs j left join client c on c.key = j.cKey where j.key='.$this->p['reckey'];
if ( $result = $db->query($sql) )
{
if ($result->num_rows > 0)
{
$l = mysqli_fetch_all( $result, $resulttype = MYSQLI_ASSOC );
$this->res_array['info'] = $l[0];
}else{
$this->errors[] = 'No such job # '.$this->p['reckey'];
$this->res_array['info']=[];
}
}else{
$this->errors[] = 'Query failed!';
$this->res_array['info']=[];
}
$this->res_array['errors'] = $this->errors;
echo json_encode ($this->res_array);
Here are two examples of what the data looks like when it arrives at the web client before it is decoded by JSON. Note the difference in the "info" element.
response {"info":{"job":"999","client":"My Company, Inc. ","project":"This Project"},"errors":[]}
error response {"info":[ ],"errors":["No such job # 0"]}
In the successful response I have an object/associative array where I would use the
for (variable in object) {...}
In the blank response I just get the standard array [ ] square brackets where I would use the
for (step = 0; step < info.length; step++) {}
This occurs of course because I am specifying a blank array in the php code above.
My question is simple how can I change my php code so a blank associtive array is transmitted?

The only example I have seen on line is in the manual where you create an empty class and then instantiate an object from that.
Sounds like you've answered your own question!
Since in JavaScript an object and an associative array are basically the same thing all you have to do is replace this line:
$this->res_array['info']=[];
With this one:
$this->res_array["info"] = new StdClass;
Or if you want to make the change only before sending the response you could check for an empty info array and replace it with an empty class.
if(!count($this->res_array["info"]))
$this->res_array["info"] = new StdClass;

I would suggest to take the best of both worlds, and let PHP generate an array of associative arrays, even though you expect at the most one, but at least you'd use the same structure for when you have none.
So change:
$this->res_array['info'] = $l[0];
to:
$this->res_array['info'] = $l;
And then in JavaScript do:
for (var step = 0; step < info.length; step++) {
for (variable in info[step]) {
// ...
}
}
... and if you still need to, you can deal with the no-data condition separately in JavaScript. Something like:
if (errors.length) {
// deal with this case...
}

Related

Filter API response with PHP

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;
}

Can't parse XMLHttpRequest.response to Object or Array

I'm trying to refresh the content of my cells of an table. Therefore, I have a JavaScript which contains an AJAX request to a .php file, which creates my content that I want to insert into my table via JavaScript. The .php files last command is something like echo json_encode($result);.
Back in the JavaScript it says:
var testarray = xmlhttp.response;
alert(testarray);
But the outut from the alert looks like:
{"1":{"1":"3","2":"0","3":"2","4":"0"}}{"1":{"1":"3","2":"0","3":"2","4":"0"},"2":{"1":"2","2":"1","3":"1","4":"1"}}...
So it seems the variable testarray isn't handled as an array but as a string. I already tried var testarray = JSON.parse(xmlhttp.response), but this doesn’t work. Neither does eval() works.
I don't know what to do, so the response of my request becomes an object.
There are 2 strange things in your json:
this part is not json valid: ...}{...
two object should be separated by comas
The notation is object with string indexes not array with int indexes
it should be something like: [[1,2,3,4],[5,6,7,8]]
for the point 1. it looks like you have a loop that concatenate many json
for the point 2. the object notation can be used as an array so it doesn't matter
Some code:
//the folowing code doesn't work: }{ is not parsable
var a=JSON.parse('{"1":{"1":"3","2":"0","3":"2","4":"0"}}{"1":{"1":"3","2":"0","3":"2","4":"0"},"2":{"1":"2","2":"1","3":"1","4":"1"}}');
//the folowing code work and the object can be used as an array
var a=JSON.parse('{"1":{"1":"3","2":"0","3":"2","4":"0"},"2":{"1":"2","2":"1","3":"1","4":"1"}}');
alert(JSON.stringify(a[1]));
//the folowing code displays the real notation of a javascript array:
alert(JSON.stringify([1,2,3,4]));
I think that the problem here might be that your arrays do not have index 0.
e.g. if you output this from the server - it would produce an object:
$result = [];
for ($i = 1; $i < 5; $i++) $result[$i] = $i;
echo json_encode($result); // outputs an object
if you output this from the server - it would produce an array:
$result = [];
for ($i = 0; $i < 5; $i++) $result[$i] = $i;
echo json_encode($result); // produces an array
Anyways, even if your server outputs array as object - you should still be able to access it normally in javascript:
var resp = xmlhttp.responseText, // "responseText" - if you're using native js XHR
arr = JSON.parse(resp); // should give you an object
console.log(arr[1]); // should give you the first element of that object

AS#3 organize variables loaded from PhP

I am having a problem of how to organize my variables in flash that are from a PHP script.Ideally i want them in an array type format so i can loop through them.Below is some code to go with.
function completeHandler(evt:Event){ // after loading the php
var symbolsArray:Array = new Array()
symbolsArray.push(evt.target.data.symbol_1);// php variable named: symbol_1, symbol_2
trace(evt.target.data);
}
The above is allworking, the PHP variables are listed as symbol_1, symbol_2 etc
Instead of pushing each variable separably into the array i want a loop, along the lines of:
function completeHandler(evt:Event){
var symbolsArray:Array = new Array()
var counter =1
symbolsArray.push(evt.target.data.symbol_+counter); this is the issue
trace(symbolsArray[0]); //returns NaN
}
Below is the php return vars to flash to give an idea:
$returnVars['symbol_1'] = $virtualReel1[0];
$returnVars['symbol_2'] = $virtualReel1[1];
$returnVars['symbol_3'] = $virtualReel1[2];
$returnVars['symbol_4'] = $virtualReel2[0];
$returnVars['symbol_5'] = $virtualReel2[1];
//etc
$returnString = http_build_query($returnVars);
echo $returnString;
symbolsArray.push(evt.target.data["symbol_"+counter]);
If you need to dynamically query properties of an object, you address it as an Array or a Dictionary, by a string key, which can be dynamically formed. Works on anything.
The returned data can be treated as an Object (containing Objects) so you can loop thru it like so:
function completeHandler(evt:Event)
{
var symbolsArray:Array = new Array();
for each (var obj:Object in evt.target.data)
{
symbolsArray.push(obj);
}
}
If you know all items are oif same type, you can cast the object. eg: if all Numbers:
symbolsArray.push(Number(obj));
Or Strings:
symbolsArray.push(String(obj));

json encoding 2 dimension array

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/

Get Value of PHP Array

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; } }

Categories