Why does this JSON array appear empty? - php

I am using a webservice to synchronize products from our distributor. As a first step, I have built a table to display the data to verify that everything is working properly. I have been able to successfully retrieve product descriptions using the following function:
function get_description($api_key, $item){
$url = 'http://www.stl-distribution.com/webservices/json/GetProductDescription.php';
$post_vars = 'api_key='.$api_key.'&item='.$item;
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST,1);
curl_setopt($ch, CURLOPT_POSTFIELDS,$post_vars);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION,1);
curl_setopt($ch, CURLOPT_HEADER,0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
$return_data = curl_exec($ch);
$json_array = json_decode($return_data,true);
return $json_array;
}
I am displaying the information using a foreach loop as follows:
<table>
<tr>
<th>ISBN</th>
<th>Description:</th>
<th>Categories:</th>
<th>Options:</th>
</tr>
<?php foreach($product_ISBNs as $item) : ?>
<tr>
<td class="center"><?php echo $item[0]?></td>
<td class="center"><?php $item_description = get_description($api_key,$item[0]); echo $item_description['description'];?>
<td class="center"><?php $item_data = get_meta_data($api_key,$item[0]); echo $item_data['product_type']; ?>
</tr>
<?php endforeach?>
</table>
While I have successfully been able to retrieve the description using the get_description() function, I consistently get the following error from the get_meta_data() function:
Notice: Undefined index: product_type in C:\xampp\htdocs\STLImport\view\user_form.php on line 21
The code for the get_meta_data() function is as followss:
function get_meta_data($api_key, $item){
$url = 'http://www.stl-distribution.com/webservices/json/GetProductMetaBasic.php';
$post_vars = 'api_key='.$api_key.'&item='.$item;
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST,1);
curl_setopt($ch, CURLOPT_POSTFIELDS,$post_vars);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION,1);
curl_setopt($ch, CURLOPT_HEADER,0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
$return_data = curl_exec($ch);
$json_array = json_decode($return_data,true);
return $json_array;
}
When I do a print_r() immediately before the return $json_array; statement I get the following error:
Array ( [0] => Array ( [error] => "" not found ) )
According to our distributor's website, our requests are being sent and received. Every time I refresh the page my usage stats go up. So, it appears that either no data is being returned, or I am not referencing it correctly. I know that these products exist in the database because it is returning the description. Therefore, I must not be referencing it correctly but I can't find where my error is. I have tried referencing it using various combinations to no avail. The webservice documentation gives this example for how the data should be returned:
{
"9781434768513":
{
"isbn13":"9781434768513",
"isbn":"1434768511",
"upc":"000000912992",
"title":"Crazy Love",
"subtitle":"Overwhelmed By A Relentless God",
"contributor1":"Chan, Francis",
"contributor2":"Yankoski, Danae",
"contributor3":"",
"vendor":"David C. Cook",
"release_date":"20080430",
"retail":"14.99",
"binding":"Paperback",
"product_type":"Books",
"category1":"Christian Living",
"category2":"",
"category3":"",
"grade_level_start":"",
"grade_level_end":"",
"inventory_updated":"20100825 11:25",
"tn_available":993,
"tn_onorder":240,
"nv_available":735,
"nv_onorder":0,
"image_small":"http:\/\/www.stl-distribution.com\/covers\/7814\/sm-9781434768513.jpg",
"image_medium":"http:\/\/www.stl-distribution.com\/covers\/7814\/md-9781434768513.jpg",
"image_large":"http:\/\/www.stl-distribution.com\/covers\/7814\/lg-9781434768513.jpg"
}

It seems that my get_meta_data() function had an error in it. My API provider informed me that this line
$post_vars = 'api_key='.$api_key.'&item='.$item;
Should have been
$post_vars = 'api_key='.$api_key.'&items='.$item;
Notice the addition of an 's'. So, $json_array appeared empty because it was empty. My other function worked because it did not require the 's' as GetProductMetaBasic did.
In addition, this line
<td class="center"><?php $item_data = get_meta_data($api_key,$item[0]); echo $item_data['product_type']; ?>
Should have been
<td class="center"><?php $item_data = get_meta_data($api_key,$item[0]); echo $item_data[$item[0]]['product_type']; ?></td>
because, as the sample data implied, the array was multidimensional. The desired value (product_type) was contained within the $item[0] array. Therefore, $item_data['product_type'] did not exist.

Related

How to extract and access data from JSON with PHP when some data changes?

I am trying to bring in some API data to a directory in wordpress.
The data I am trying to get is just crypto coin price, none of the other information but because its format is sort of nested (?) it doesnt seem to work.
{
"bitcoin": {
"usd": 16808.82
}
}
This is my code so far:
<?php
$handle = curl_init();
$url = get_post_meta($entity-\>post()-\>ID, '\_drts_field_004', true);
// Set the url
curl_setopt($handle, CURLOPT_URL, $url);
// Set the result output to be a string.
curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
curl_setopt($handle, CURLOPT_SSL_VERIFYPEER, false);
$output = curl_exec($handle);
curl_close($handle);
$data = json_decode($output);
echo $output;
var_dump($data);
The results are:
{
"bitcoin":{
"usd":16833.02
}
}
object(stdClass)#10399 (1) {
["bitcoin"]=> object(stdClass)#10492 (1) {
["usd"]=> float(16833.02)
}
}
In this example I am only after the 16833.02
I am trying to do this for lots of different coins, the "usd" will always be the same but the "bitcoin" will change when other coins.
How can I echo only the number?
I have tried lots of variations of echo but cannot get it? Is it possible to do something like:
echo $data['bitcoin']['usd'];
but rather than bitcoin use * ?
As in anything can be there?
You can access the usd value by decoding the JSON to an array instead of an object like this
$data = json_decode($output, true);
$usd = current($data)['usd'];

array becomes null because I can't send product id with get_file_content

I cannot see the details of the product I have selected in my product list with the woocommerce rest api
The main problem is that when I write the id of the product, I see it as json, but I have a problem when I want to include it in an array.
The main problem is that I can't send product id to single_product_connect.php with get_file_content, so it shows $ data array empty
form code;
<form action="single_product.php" name="update" method="get">
<td><input type="submit" name="edit"id="edit" value="<?= $row['id']; ?>"/></td></form>
single_product.php code;
<?php
$data = file_get_contents('http://localhost/api-woocommerce/single_product_connect.php');
$data = json_decode($data, true);
?>
<?php foreach ( $data as $row ) : ?>
<?= $row['id']; ?>
<?= $row['name']; ?> //I wrote a small piece for testing
<?php endforeach; ?>
single_product_connect.php code;
<?php $product_id = $_GET['edit'];?>
<?php echo json_encode($woocommerce->get("products/{$product_id}",$data)); ?>
error screen;
Warning: Invalid argument supplied for foreach() in C:\xampp\htdocs\api-woocommerce\single_product.php on line 19////The code in line 19:
<?php foreach ( $data as $row ) : ?>
When you use file_get_contents to get single_product_connect.php with http you can pass "edit" as a parameter if you concatenate query parameters to your url.
Try this change:
$id = /*some id*/;
$data = file_get_contents('http://localhost/api-woocommerce/single_product_connect.php?edit='.$id);
As you've mentioned can't send product id to single_product_connect.php with get_file_content so, when you're calling the remote url, the return value is an empty string which on json_decode() becomes null. You can check this by just adding this json_last_error() after json_decode() like this
$data = json_decode($data, true);
$erorr = json_last_error();
var_dump($data);
echo $error;
You can first append the product_id to the url and then can make the call to the url using file_get_contents like this
$url = "http://localhost/api-woocommerce/single_product_connect.php?product_id=<product_id>";
$data = json_decode(file_get_contents($url), true);
but I would suggest you to either use curl (recommended) or fsockopen.
With curl, it's very easy
// create curl resource
$ch = curl_init();
// set url
$url = "http://localhost/api-woocommerce/single_product_connect.php?product_id=<product_id>";
curl_setopt($ch, CURLOPT_URL, $url);
//return the transfer as a string
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// $output contains the output string
$output = curl_exec($ch);
// close curl resource to free up system resources
curl_close($ch);
$data = json_decode($output, true);
if (json_last_error() !== JSON_ERROR_NONE) {
echo json_last_error_msg();
exit();
}
foreach ($data as $row) {
// do something
}

PHP - How to share JSON data between files

So I'm trying to make a simple API, I have tried lots of different things. I want to show a random number on my JSON object and a token to go with it, then store both in a database. I don't want this to happen when you visit the webpage I want the data to get sent to a DB and generated from a separate page.
The first step in this is getting data from a different file.
Here's what I tried first:
index.php:
<?php
$odds = rand(1, 100);
?>
<pre style="word-wrap: break-word; white-space: pre-wrap;">
{
"odds": <?php echo $odds;?>
}
</pre>
Here's the file I'm trying to get the data from:
<?php
$url = "https://flugscoding.com/random/";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_USERAGENT, "Riverside API");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
if(!$response = curl_exec($ch)) {
echo curl_error($ch);
}
curl_close($ch);
$data = json_decode($response, true);
echo $data->odds;
?>
Error:
Notice: Trying to get property 'odds' of non-object in D:\xxamp\htdocs\random\perp.php on line 16
What I tried after:
index.php:
<?php
$values = array("odds"=>rand(1, 100));
echo json_encode($values);
?>
Here's the file I'm trying to get the data from:
<?php
$json = file_get_contents("index.php");
echo $json;
// echo $json->odds;
?>
Error:
It doesn't show any data or errors, just a blank screen.
Does anyone have any solutions to this problem? I'm trying to make a provably fair system for a friend.
You're really close in both your examples:
#1
$data = json_decode($response, true);
echo $data->odds;
You're passing true into json_decode which makes it an associative array, not an object. So you will need to get the odds with $data['odds']; instead.
#2
$json = file_get_contents("index.php");
echo $json;
file_get_contents can either fetch a local file or remote file. In this case, you're passing a local file, so $json is the contents of the PHP code.
You can either:
(a) redesign it so that index.php is a function, and you can call the function from different files
(b) call index.php remotely and parse the results
a. Create a function in index.php that can get the odds:
<?php
function getData() [
return array("odds"=>rand(1, 100));
}
Then, in another file, you can:
<?php
require_once 'index.php';
$data = getData(); //now you have access to $data['odds'];
b. Call index.php remotely, like this:
$json = file_get_contents("http://localhost/index.php");
print_r(json_decode($json, true));

How to return data using cURL call

This returns a token, like: {"token":"260e5b8adf74af6be5dfa250c5ad93c8"}
And I want just want the content part: 260e... Which I think I can get it by using $getInfo['token'], right?
$user="admin";
$password="Moodle15!";
$services="moodle_mobile_app";
$url = "https://localhost/moodle/login/token.php?username=".$user."&password=".$password."&service=".$services."";
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURL_RETURNTRANSFER, true);
$getURL = curl_exec($ch);
$getInfo = json_decode($getURL, true);
$displayToken = $getInfo['token'];
echo $displayToken;
curl_close($ch);
And I don't know what's going on with the CURL_RETURNTRANSFER.
And the error:
Notice: Use of undefined constant CURL_RETURNTRANSFER - assumed 'CURL_RETURNTRANSFER' in C:\xampp\htdocs\moodle\cURL_script.php on line 12
Warning: curl_setopt() expects parameter 2 to be long, string given in C:\xampp\htdocs\moodle\cURL_script.php on line 12
{"token":"260e5b8adf74af6be5dfa250c5ad93c8"}
EDITED:
And if I had:
{"id":4,"username":"Jhon","firstname":"smith","lastname":"Reches","fullname":"Jhon smith","email":"Jhon.smith#example.com","department":"","firstaccess":0,"lastaccess":0,"description":"","descriptionformat":1,"profileimageurlsmall":"http:\/\/localhost\/moodle\/pluginfile.php\/25\/user\/icon\/f2","profileimageurl":"http:\/\/localhost\/moodle\/pluginfile.php\/25\/user\/icon\/f1","groups":[],"roles":[{"roleid":5,"name":"","shortname":"student","sortorder":0}],"enrolledcourses":[{"id":3,"fullname":"Game Design","shortname":"Game Design"},{"id":2,"fullname":"Grup de Recerca","shortname":"Grp. Recerca"}]}
How can I acces to 'username'? or 'fullname' when you know there are many 'fullname' in it?
EDITED2:
New code I have now:
$token = "260e5b8adf74af6be5dfa250c5ad93c8";
$funcion="core_enrol_get_enrolled_users";
$courseid="3";
$format="json";
$url= "https://localhost/moodle/webservice/rest/server.php?wstoken=".$token."&wsfunction=".$funcion."&courseid=".$courseid."&moodlewsrestformat=".$format."";
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$getURL = curl_exec($ch);
$getInfo = json_decode($getURL, true);
$email = $getInfo[2]['email'];
echo $email."</br>";
curl_close($ch);
Now $email contains jhon.smith#example.com but I have many results, how can I manage to display all of them with a foreach? Because it is a multidimentional array. See below.
[{"id":4,"username":"jhon1.smith1","firstname":"Jhon1","lastname":"Smith1","fullname":"jhon1 smith1","email":"jhon1.smith1#example.cat","department":"","firstaccess":0,"lastaccess":0,"description":"","descriptionformat":1,"profileimageurlsmall":"http:\/\/localhost\/moodle\/pluginfile.php\/25\/user\/icon\/f2","profileimageurl":"http:\/\/localhost\/moodle\/pluginfile.php\/25\/user\/icon\/f1","groups":[],"roles":[{"roleid":5,"name":"","shortname":"student","sortorder":0}],"enrolledcourses":[{"id":3,"fullname":"Game Design","shortname":"Game Design"},{"id":2,"fullname":"Grup de Recerca","shortname":"Grp. Recerca"}]},{"id":5,"username":"jhon1.smith1","firstname":"Josep","lastname":"jhon1 ","fullname":"jhon1 smith1","email":"jhon1.smith1#example.cat","department":"","firstaccess":0,"lastaccess":0,"description":"","descriptionformat":1,"profileimageurlsmall":"http:\/\/localhost\/moodle\/pluginfile.php\/26\/user\/icon\/f2","profileimageurl":"http:\/\/localhost\/moodle\/pluginfile.php\/26\/user\/icon\/f1","groups":[],"roles":[{"roleid":5,"name":"","shortname":"student","sortorder":0}],"enrolledcourses":[{"id":3,"fullname":"Game Design","shortname":"Game Design"},{"id":2,"fullname":"Grup de Recerca","shortname":"Grp. Recerca"}]},{"id":6,"username":"jhon1.smith1","firstname":"jhon1","lastname":"smith1","fullname":"jhon1 smith1","email":"jhon1.smith1#example.cat","department":"","firstaccess":0,"lastaccess":0,"description":"","descriptionformat":1,"profileimageurlsmall":"http:\/\/localhost\/moodle\/pluginfile.php\/32\/user\/icon\/f2","profileimageurl":"http:\/\/localhost\/moodle\/pluginfile.php\/32\/user\/icon\/f1","groups":[],"roles":[{"roleid":1,"name":"","shortname":"manager","sortorder":0}],"enrolledcourses":[{"id":3,"fullname":"Game Design","shortname":"Game Design"},{"id":2,"fullname":"Grup de Recerca","shortname":"Grp. Recerca"}]},{"id":7,"username":"jhon1.jhon1","firstname":"jhon1","lastname":"jhon1","fullname":"jhon1 smith1","email":"jhon1.smith1#example.cat","department":"","firstaccess":0,"lastaccess":0,"description":"","descriptionformat":1,"profileimageurlsmall":"http:\/\/localhost\/moodle\/pluginfile.php\/35\/user\/icon\/f2","profileimageurl":"http:\/\/localhost\/moodle\/pluginfile.php\/35\/user\/icon\/f1","groups":[],"roles":[{"roleid":5,"name":"","shortname":"student","sortorder":0}],"enrolledcourses":[{"id":3,"fullname":"Game Design","shortname":"Game Design"}]},{"id":8,"username":"jhon1.smith1","firstname":"jhon","lastname":"smith1","fullname":"jhon1 smith1","email":"jhon1.smith1#example.cat","department":"","firstaccess":0,"lastaccess":0,"description":"","descriptionformat":1,"profileimageurlsmall":"http:\/\/localhost\/moodle\/pluginfile.php\/41\/user\/icon\/f2","profileimageurl":"http:\/\/localhost\/moodle\/pluginfile.php\/41\/user\/icon\/f1","groups":[],"roles":[{"roleid":3,"name":"","shortname":"editingteacher","sortorder":0}],"enrolledcourses":[{"id":3,"fullname":"Game Design","shortname":"Game Design"}]}]
and I wish:
foo#example.com
bar#example.com
foo2#..
CURL_RETURNTRANSFER needs to be changed to CURLOPT_RETURNTRANSFER.
That is affecting what is returned by curl_exec() so you aren't getting the JSON string in $getURL.
Once the constant is corrected, the rest of your code is correct.
EDIT (added):
When dealing with JSON, it helps to format it so it's easier to read, I use jsonlint.com.
Then looking at the structure, if you had:
$data = json_decode($response, true);
Accessing the fullnames from enrolledcourses would be:
echo $data['enrolledcourses'][0]['fullname'];
Or if you were using object notation, rather than associative array:
echo $data->enrolledcourses[0]->fullname;

PHP dom parsing

I'm trying to get the values of the following table. I tried both curl/regex (I know it's not recommended) and DOM separately, but wasn't able to get the values properly.
There are multiple rows in the page, so I'll need to use a foreach. I need an exact match of the structure below.
<tr>
<td width="75" style="NS">
<img src="NS" width="64" alt="INEEDTHISVALUE">
</td>
<td style="NS">
NS
</td>
<td style="NS">INEEDTHISVALUETOO</td>
</tr>
NS = Non-static values. They change for each td and a since it's a colored (inline css) table. They may contain special characters like ; / or numbers/alphabetical characters.
I'm using simple_html_dom class which can be found here : http://htmlparsing.com/php.html
I'm using the code below to get all td's, but I need more specific output (I included the table row above)
What I've tried so far :
$html = file_get_html("URL");
foreach($html->find('td') as $td) {
echo $td."<br>";
}
REGEX & CURL
$site = "URL";
$ch = curl_init();
$hc = "YahooSeeker-Testing/v3.9 (compatible; Mozilla 4.0; MSIE 5.5; Yahoo! Search - Web Search)";
curl_setopt($ch, CURLOPT_REFERER, 'http://www.google.com');
curl_setopt($ch, CURLOPT_URL, $site);
curl_setopt($ch, CURLOPT_USERAGENT, $hc);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$site = curl_exec($ch);
curl_close($ch);
preg_match_all('#<tr><td width="75" style="(.*?)"><img src="/folder/link/(.*?)" width="64" alt="(.*?)"></td><td style="(.*?)">(.*?)</td><td style="(.*?)">(.*?)</td></tr>#', $site, $arr);
var_dump($arr); // returns empty array, WHY?
You can do it like this without a library:
$results = array();
$doc = new DOMDocument();
$doc->loadHTML($site);
$xpath = new DOMXPath($doc);
foreach ($xpath->query('//tr') as $tr) {
$results[] = array(
'img_alt' => $xpath->query('td[1]/img', $tr)->item(0)->getAttribute('alt'),
'td_text' => $xpath->query('td[last()]', $tr)->item(0)->nodeValue
);
}
print_r($results);
It will give you:
Array
(
[0] => Array
(
[img_alt] => INEEDTHISVALUE 1
[td_text] => INEEDTHISVALUETOO 1
)
[1] => Array
(
[img_alt] => INEEDTHISVALUE 2
[td_text] => INEEDTHISVALUETOO 2
)
)
Relevant documentation: PHP: DOMXPath::query

Categories