Why is my variable variable not referencing the json data? - php

I have tried to understand and solve this issue to no end. I think I'm close in that I suspect I'm simply referencing my json data incorrectly, but I cannot figure out how to do it right. Here's the use case.
I'm building a simple ledger system to track crypto transactions. The system also does some nice tallying of coin totals, calculates coin values in USD, and caculates overall portfolio value etc.
I let the user track coins of their choice that sit in an array called $coins. The $coins array is initialized earlier in my code via a database call and contains $coin->ID and the $coin->symbol.
To determine coin values in USD, I make a call out to CryptoCompare using their API, which, after grabbing the coin symbols from my $coins array, looks something like this:
https://min-api.cryptocompare.com/data/pricemulti?fsyms=ADA,BTC,ETH,LTC&tsyms=USD
Just pop that URL into a browser to view the results set.
$price_request_data stores that data after being decoded.
Now my problem arises when I try to reference the JSON data via my $coins loop. I can reference the data just fine if I use a direct reference such as:
$price_request_data->BTC->USD
That produces a value of 15592.
But obviously I want to loop through my $coins loop and dynamically create variables for each coin to hold its respective price. When I try to reference the JSON data in this way, it fails to retrieve the price ( 15592) and instead returns 0.
// ----------------------------------------------------------
// GET CURRENT PRICES
$apiurl = "https://min-api.cryptocompare.com/data/pricemulti?fsyms=ADA,BTC,ETH,LTC&tsyms=USD";
$price_request = wp_remote_get( $apiurl );
if( is_wp_error( $price_request ) ) {
return false;
}
$price_request_body = wp_remote_retrieve_body( $price_request );
$price_request_data = json_decode( $price_request_body );
if( ! empty( $price_request_data ) ) {
echo $price_request_data->BTC->USD . "<br />"; // PRODUCES 15592
foreach( $coins as $coin ) {
$pricereqdata = "price_request_data->" . $coin->symbol . "->USD";
echo $$pricereqdata; // PRODUCES 0
// Generate the variable name string i.e. "curpricebtc"
$curprice = "curprice" . strtolower( $coin->symbol );
// Format the current coin's price
$$curprice = number_format( ceil_dec( $$pricereqdata, 2 ), 2, ".", "" );
}
}
This is the vardump of $price_request_data:
object(stdClass)#1527 (4) {
["ADA"]=>
object(stdClass)#1528 (1) {
["USD"]=>
float(0.4469)
}
["BTC"]=>
object(stdClass)#1535 (1) {
["USD"]=>
float(15592)
}
["ETH"]=>
object(stdClass)#1536 (1) {
["USD"]=>
float(757.13)
}
["LTC"]=>
object(stdClass)#1539 (1) {
["USD"]=>
float(291.21)
}
}
I'm using PHP7 and I know some reference rules changed, but I was not able to determine if that's my issue. I swear it's just the way I'm referencing it with a variable variable, but I'm not experienced enough to know why.
Any wisdom is much appreciated.

OK:
Q: Does "$price_request_data" equal {"ADA":{"USD":0.4738},"BTC":{"USD":15486.46},"ETH":{"USD":786.47},"LTC":{"USD":306.48}} (or equivalent)?
<= Your comment, "// WORKS", implies "yes"
Q: Where is "$coin" initializated? What is its value?
Q: What is a value of "$pricereqdata"?
Q: Does "$$pricereqdata" create a new variable for you? What is it? What is its value?
In other words, exactly what do you mean by "// FAILS"???

Related

Is it possible to concatenate two values in an array together?

I’m new to PHP so this might be a very long questions. First of all I can’t normalise the database the way it has been designed it has to be kept like this. I’ll explain the scenario first: I have locations on a map, those locations can have as many products attached to them as possible. My issue is that I want to concatenate two values together in an array to make them into a string so I can store it in the db and then use it.
I’m having issues with a particular record, this record 1234 is causing me issues. As it has two Ratings attached to it but I need to concatenate them and put them into another array so I can store in my database in a particular field as strings instead of separate ints.
Below is the code, as you’ll see I did a if statement inside the code I want to use to debug what is happening in that particular record.
$ratingString = array();
$rating = 0;
foreach( //not sure if this foreach is related to the question)
if(true == isset($ratingString[$location[‘id’]])){
echo ‘in set’;
$ratingString[$location[‘id’]][‘ratingString’] = strval( $ratingString[$location[‘id’]][‘ratingString’]).’,’.$rating;
}else {
if($location[‘id’] == 1234){
echo ‘not in set’
$ratingString[$location[‘id’]][‘ratingString’] = $rating;
Print_r($ratingString);
} }
When I debug this, it shows me two variables in rating string.
Not in set
string() “ratingString”
array(1){
[1234] =>
array(1) {
[“ratingString”] =>
int(2)
}
}
Not in set
string() “ratingString”
array(1){
[1234] =>
array(1) {
[“ratingString”] =>
int(3)
}
}
So what I need help with, is how could I concatenate the two so that it would be [ratingString] => string 2,3 and how would I change my code so that it would work for all my locations and not just this particular record.

php loop to pull json data fields

Hello everyone and thanks for your time. I am trying to set up a loop to pull specific fields from a json api feed. The json feed can be seen here:
https://uysmiami.com/search/api_server_custom.php
I am trying to set up a loop to grab data from specific fields from the feed but with my limited php am grabbing other stuff as well. The results of my loop are can be seen at:
http://uysmiami.com/search/stevetest.php
the code I'm using is:
<?php
$json = file_get_contents('https://api.iyba.pro/vessel?key=95d30b94b3a7e8b8c2df379fb00816960f86e203&id=80393');
$data = json_decode($json,true );
foreach($data as $vdata)
{ foreach($vdata as $number){
echo "Name: ".$number['ListingOwnerName']."<br />";
} }
?>
how can I pull the fields I want and not the first two and last 4 lines of meaningless stuff?
Thanks again.
I got your desired results doing something like this:
$dataFromUrl = file_get_contents( 'https://uysmiami.com/search/api_server_custom.php' );
$dataEn = json_decode( $dataFromUrl, TRUE );
foreach( $dataEn['V-Data'] as $vData )
{
if ( isset( $vData['ListingOwnerName'] ) )
{
echo "Name: " . $vData['ListingOwnerName'] . "<br />";
}
}
I am not sure if you need to loop through more things which is why you nested another loop, but for the V-Data array from the API shown, that got all the names without any numbers.

Array key exists but can't be read from a cookie

This is a weird one, so bear with me. Asking you guys really is my last resort.
To be clear, I'm using Kohana 3.3, although I'm not even sure that's related to the problem.
I'm using a cookie to track read items on a website. The cookie contains a json_encoded array. Adding to that array isn't a problem, objects are added every time a new item is read. An item in the array contains an object with the last_view_date and a view_count For the sake of updating the view count, I need to check whether the item has been read already using array_key_exists and then add to the view count. Here's how I'm setting the cookie:
// Get the array from the cookie.
$cookie_value = Cookie::get_array('read_items');
// Update the view_count based on whether the id exists as a key.
$view_count = (array_key_exists($item->id, $cookie_value)) ?
$cookie_value[$item->id]['view_count'] + 1 : 1;
// Create the item to be added to the cookie.
$cookie_item = array(
'last_view_date' => time(),
'view_count' => $view_count
);
// Push $cookie_item to the cookie array.
Cookie::push('read_items', $item->id, $cookie_item);
I've added two methods to Kohana's Cookie class, Cookie::push and Cookie::get_array, used in the code above:
class Cookie extends Kohana_Cookie {
public static function push($cookie_name, $key, $value)
{
$cookie_value = parent::get($cookie_name);
// Add an empty array to the cookie if it doesn't exist.
if(!$cookie_value)
{
parent::set($cookie_name, json_encode(array()));
}
else
{
$cookie_value = (array)json_decode($cookie_value);
// If $value isn't set, append without key.
if(isset($value))
{
$cookie_value[$key] = $value;
}
else
{
$cookie_value[] = $key;
}
Cookie::set($cookie_name, json_encode($cookie_value));
}
}
public static function get_array($cookie_name)
{
return (array)json_decode(parent::get($cookie_name));
}
}
Now, here's my problem. Running a var_dump on $cookie_value outputs the following:
array(1) {
["37"]=>
object(stdClass)#43 (2) {
["last_view_date"]=>
int(1359563215)
["view_count"]=>
int(1)
}
}
But when I try to access $cookie_value[37], I can't:
var_dump(array_key_exists(37, $cookie_value));
// Outputs bool(false);
var_dump(is_array($cookie_value));
// Outputs bool(true);
var_dump(count($cookie_value));
// Outputs int(1);
var_dump(array_keys($cookie_value));
// Outputs:
// array(1) {
// [0]=>
// string(2) "37"
// }
Added debugging code:
var_dump(isset($cookie_value["37"]));
// Outputs bool(false).
var_dump(isset($cookie_value[37]));
// Outputs bool(false).
var_dump(isset($cookie_value[(string)37]));
// Outputs bool(false).
I hope it's clear enough.
Take a look at json_decode. Currently, you're casting the result to an array. If you pass true as the second parameter to json_decode, you'll get an array back instead of a stdObject.
The problem may also be related to you checking int vs string keys. You could test by running this code on your server:
<?php
$one = array("37" => "test");
$two = array(37 => "test");
var_dump(array_key_exists(37,$one)); // true or false?
var_dump(array_key_exists(37,$two)); // true
?>
Access the value using:-
$cookie_value["37"]
"37" (key) is in string format.. You are specifying it as integer ($cookie_value[37])

undefined index in multidimensional array

I'm using amazon products API.
$ItemAttr = $Item['ItemAttributes'];
Now $ItemAttr contains a multidimensional array.
if(is_array($ItemAttr["Author"])){$Author = implode(", ", $ItemAttr["Author"]);
}else{
$Author = $ItemAttr["Author"];}
Now when i use the above code i'm getting Undefined index: Author in line 1 and line 3
I tried like this
if(isset($ItemAttr["Author"])) {
if(is_array($ItemAttr["Author"])){$Author = implode(", ", $ItemAttr["Author"]);
}else{
$Author = $ItemAttr["Author"];}
}
It eliminates that error.
But later, When I use code like this $RetVal = array( 'Author' => $Author); i'm getting Undefined variable : Author error
Can anyone tell me the proper way?
Please note: $Item['ItemAttributes']; may or may no contain Author key. I mean if the returned product is a book, the array will return author key. Else it will not..
Initialize the empty variable $Author on top?
$Author = ""; //initialize here
if(isset($ItemAttr["Author"]))
{
if(is_array($ItemAttr["Author"]))
{
$Author = implode(", ", $ItemAttr["Author"]);
}
else
{
$Author = $ItemAttr["Author"];
}
}
I implemented the amazon books api just last month and i remember this exact same problem. How lucky are you as i never had me to help :(
Amazon is very annoying because there is no consistency within their returned structure (well, except for what's below, but that makes it annoying to consume):
if one item is returned, it's an OBJECT
if multiple items are returned, it's an ARRAY
if nothing is returned, NOTHING exists at all
Personally i think they should have used empty arrays at least, and stick to arrays. You can always add objects to arrays >< but at least the structure would be consistant.
The way i got around it, was to create a new representation of the returned structure which GUARANTEED that everything was an array and that the WHOLE STRUCTURE was pre-defined. This way i could later access the data knowing 100% that it won't give me errors like it doesn't exist or is being accessed as an object when it is an array.
First, create the structure how you want it to be such as:
$structure = array(
'isbn' => '',
'authors' => array(),
'pictures' => array(),
'title' => ''
);
Then create a function or object method (depending on your style) to consume the amazon data returned and find what it can and insert it into your custom structure.
Remember to check that first it exists, and then if it is an array or an object so you know how to access it. It helps to print out a few returned results from amazon with a few different books.
Then, to access details about the book, you can rely on the data in the $structure ;) everything is an array, and everything is guaranteed to exist so doing:
foreach ($structure['authors']...
Won't produce an error that its not an array, doesn't exist or is in fact an object!!!
The sort of pseudo code would be:
$returned_amazon_data = get_amazon_data('http://amazon.com/api/book=1234567');
$book = consume_amazon_result($returned_amazon_data);
if ($book) {
//print out the authors, if no authors were found, will just stay blank as it's GUARANTEED to always be an array of strings
print implode($book['authors']);
}
Have fun! I know i did(nt)...
You can combine your two conditional statements, as well as predefine $Author:
$Author = '';
if(isset($ItemAttr["Author"]) && is_array($ItemAttr["Author"])){
$Author = implode(", ", $ItemAttr["Author"]);
}elseif(isset($ItemAttr["Author"])){
$Author = $ItemAttr["Author"];
}
this should eliminate both errors.

Build a json in php from POST data

I need to update a json list of object via url post data. For example, with url:
http://myweb.com/index.php?name=Peter&surname=Brown
in php, using get method:
$name = $_GET["name"];
$surname = $_GET["surname"];
$json = array();
$json["nombre"] = $name;
$json["lat"] = $lat;
$data[] = $json;
$json_end= json_encode($data);
and json_end efectively is done like I want:
[{"name":"Peter","surname":"Brown"}]
My question is about how I can do it incrementing the json, in order to build an array like:
[{"name":"Peter","surname":"Brown"}]
[{"name":"newname","surname":"newsurname"}]
// and so on
each time user use the url with new parameters.
Do I need to write to a file, or to database? Any tips will be apreciated.
The idea is to be able that any user can add some dat using url. I tried to store the json to a fiel but the storing is durable only along the current session.
<?
/* This needs to be at the top of your file, without ANYTHING above it */
session_start();
/* ... */
if(!array_key_exists('entries', $_SESSION))
{
$_SESSION['entries'] = array();
}
$_SESSION['entries'][] = array("name" => $_GET["name"], "surname" => $_GET["surname"]);
$json_string = json_encode($_SESSION['entries']);
This would produce a single JSON. However I don't know whether you meant to or not, but your output is a series of separate JSONs. You could do this by replacing the last line above with:
$json_string = '';
foreach($_SESSION['entries'] as $entry){
$json_string.= json_encode($entry) . "\n";
}
You would also probably want a way to reset/empty the array. In which case I'd change the if test from:
if(!array_key_exists('entries', $_SESSION))
to:
if(!array_key_exists('entries', $_SESSION) || array_key_exists('reset', $_GET))
Which you could use by visiting
http://myweb.com/index.php?reset
Edit: If somewhere you add the following code:
foreach($_SESSION['entries'] as $id=>$entry){
printf("%2d: %s\n", $id, json_encode($entry));
}
You'll get a list of the json elements enumerated by their respective keys. For example, it might look like:
0: "[{\"name\":\"Peter\",\"surname\":\"Brown\"}]"
1: "[{\"name\":\"newname\",\"surname\":\"newsurname\"}]"
2: "[{\"name\":\"George\",\"surname\":\"Washington\"}]"
3: "[{\"name\":\"John\",\"surname\":\"Adams\"}]"
If you then add the following code:
if(array_key_exists('del', $_GET) && is_numeric($_GET['del']))
{
$key = (int)$_GET['del'];
if(array_key_exists($key, $_SESSION['entries']))
{
unset($_SESSION['entries'][$key]);
}
else
{
printf('<strong>ERROR: $_GET['del'] = %d but $_SESSION['entries'][%d] doesn't exist.</strong>', $key, $key);
}
}
you'll be able to delete individual json entries by specifying id as the del GET parameter.
For example,
http://myweb.com/index.php?del=2
would delete the entry corresponding to '[{"name":"George","surname":"Washington"}]';
And the remaining entries would be:
0: "[{\"name\":\"Peter\",\"surname\":\"Brown\"}]"
1: "[{\"name\":\"newname\",\"surname\":\"newsurname\"}]"
3: "[{\"name\":\"John\",\"surname\":\"Adams\"}]"
4: "[{\"name\":\"Thomas\",\"surname\":\"Jefferson\"}]"
Just make a nested array of users:
$data = array (
0 => array("name"=>"Peter","surname"=>"Brown"),
1 => array("name"=>"newname","surname"=>"newsurname")
);
echo json_encode($data);
// [{"name":"Peter","surname":"Brown"},{"name":"newname","surname":"newsurname"}]
I think it would be easiest to store the data in a session, something like this:
<?php
session_start();
if (isset($_GET['name'])) {
$_SESSION['json'][] = $_GET;
}
echo json_encode($_SESSION['json']);
?>
Edit: You may want to filter the $_GET array before storing it in the session so that you don't store values that aren't meant to be stored.
Edit: Of course, if you want to save this data for more than one session you would need to use files or a database (or perhaps a cookie). It all depends on what you want to do with the information.

Categories