PHP treats an array as an object - php

I'm not a PHP developer so I may be doing something wrong. I'm trying to decode JSON string and insert some values to mysql database. I'm getting a valid array of json objects (tested with jsonlint), so I'm adding them one by one to database. But php throws :
<b>Fatal error</b>: Cannot use object of type stdClass as array error.
This is the code :
$array = json_decode(stripslashes($_POST['data']));
for($i = 0, $l = sizeof($array); $i < $l; $i++){
$obj = $array[$i];
echo "ARRAY1: ".$array;
echo "L: ".$l;
echo "ARRAY2: ".gettype($array);
$q = 'INSERT INTO dependencies SET projectID = "1", `from` = "'.$obj->{'From'}.'", to = "'.$obj->{'To'}.'", type = "'.$obj->{'Type'}.'", cls = "'.$obj->{'Cls'}.'", lag = "'.$obj{'Lag'}.'"';
Error is thrown from line $q = 'INSERT INTO... and the printed variables show that indeed my $array is an Array :
ARRAY1: ArrayL: 2ARRAY2: array . What am I doing wrong here ?

json_decode returns an object, unless you specify you want an array with the second optional argument:
json_decode(stripslashes($_POST['data']), true);
Some other useful advice:
Use var_dump for debugging purposes. It will help you understand the structure of any objects/arrays in your code.
You should not be accepting data through post and the using it in an SQL query without any sanitation, anyways. I highly recommend you fix that asap.

You're missing a -> in the last assignment:
$obj{'Lag'}

The simplest way is as Paul pointed out and I'd advise this one. But if you ever need to cast an array as an object use:
$newObject = (object) $oldArray;

Related

How to create a blank associative array in 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...
}

PHP append each element in an array

I'm having a difficult time appending each element in an array I have in PHP for multiple OneSignal tags. Here is the result of my current JSON encoded array:
[{"value":"email#address.com"},
{"value":"email#address.com"},
{"value":"email#address.com"}]
Desired output:
[{"key":"user_email","relation":"=","value":"email#address.com"},
{"key":"user_email","relation":"=","value":"email#address.com"},
{"key":"user_email","relation":"=","value":"email#address.com"}]
Here is my current PHP code:
$jsonData = array();
$allStaffInit = mysql_query("Select * from users");
while ($staffrow = mysql_fetch_object($allStaffInit)){
$jsonData[] = $staffrow;
}
echo json_encode($jsonData);
Any help is greatly appreciated! Thanks!
Try replacing
$jsonData[] = $staffrow;
with
$object = new stdClass();
$object->key = "user_email";
$object->relation = "=";
$object->value = $staffrow->value;
$jsonData[] = $object;
I am typing this in a browser, so cannot test, but you get the idea (if you don't get the idea, ask in comments :)
If you must use the mysql_ functions, you don't need to manually construct an object or array, just get the result set as an array and use that.
while ($staffrow = mysql_fetch_assoc($allStaffInit)){
$jsonData[] = $staffRow;
}
But I seriously recommend you at least upgrade to using the mysqli extension instead. You won't really have to adjust your code much.
http://php.net/manual/en/book.mysqli.php

php traverse object using variables for property names

I have a case where I may recive one of two json objects, in this case from either the google geocode api, or the places api.
Acccessing values from the geocoding api it will look like this:
$coordinates = $data->results[0]->geometry->location;
$cache_value['lat'] = (string) $coordinates->lat;
$cache_value['lng'] = (string) $coordinates->lng;
and an almost identical structure for places.
$coordinates = $data->result->geometry->location;
$cache_value['lat'] = (string) $coordinates->lat;
$cache_value['lng'] = (string) $coordinates->lng;
In my code I've two functions to handle each case, but they are almost idential with the exception of the result vs results[0] and I'd like to combine them. I've tried to passing a varriable but it throws errors:
$result = ($place) ? 'result' : 'results[0]';
$coordinates = $data->$result->geometry->location;
Gives the following:
Notice: Undefined property: stdClass::$result[0]
I'd like to know the correct syntax to achive what im after, and any pointers on nominclature, as Im afraid this question title is a bit inpercise.
Just do:
$result = $place ? $data->result : $data->results[0];
$coordinates = $result->geometry->location;
What your code is doing, is this: It tries to resolve a property of $data object with a name of results[0], and there is none; Once again - it does not resolve 0 index of the results property, but it tries to find a property with a literal name results[0]; It would work if your object looked like this:
$obj = (object)array( 'results[0]' => 'hey there' );
If for any reason you would like to play with that, you could create a silly property like this: $data->{'results[0]'} = 5; - but it's stupid, don't do that :)
i believe php is looking for a key named results[0], its not smart enough to know that the properties name is results and you want the first member of the collection [0]
The issue is the reference of the variable name, rather than its value.
$result = ($place) ? 'result' : 'results[0]';
$coordinates = $data->$result->geometry->location;
$result is just a string and should be the actual value of either $data->result or $data->result[0].
To correct it, simply use $result to hold the value of result.
$result = ($place) ? $data->result : $data->results[0];
$coordinates = $result->geometry->location;

getting a value of a known key in php failing

I know it's my syntax, but can't find the problem.
I normally use a loop to turn any json keys into variables like this:
Sent JSON: [{\"name\":\"dolly\",\"page\":\"A4\"}]
$object = json_decode(stripslashes($_POST['myData']));
foreach ($object[0] as $key => $value)
{
$$key = preg_replace('/--+/',' ',$value);
}
So now, eg, I have $page = "A4". Works fine.
Now, rather than looping through like that, I just want to access the 'page' key (that I know is going to be there every time), and disregard anything else.
I thought this would do it, but it falls over with "Cannot use object of type stdClass as array":
$object = json_decode(stripslashes($_POST['myData']));
$page = $object[0]['page'];
This doesn't error out, but it returns nothing:
$object = json_decode($_POST['myData']);
$p = $object[0]->page;
As does
$p = $object->page;
What am I screwing up here?
Thanks for taking a look.
This seems to work fine for me?
$a='[{\"name\":\"dolly\",\"page\":\"A4\"}]';
$o=json_decode(stripslashes($a));
var_dump($o[0]->page);
string(2) "A4"
Does that help?
You will need to combine your approaches ;-)
$object = json_decode(stripslashes($_POST['myData'])); // note the stripslashes() here!
$p = $object[0]->page;
As the object encoded is an array, you do need to get the first element and then the object property as you did in your second snippet of code. You just forgot to apply stripslashes() so that json_decode() failed.

How to deserialize this string into a PHP array of key => value pairs?

I'm calling the script at: http://phat-reaction.com/googlefonts.php?format=php
And I need to convert the results into a PHP array format like the one I'm currently hard coding:
$googleFonts = array(
"" => "None",
"Abel"=>"Abel",
"Abril+Fatface"=>"Abril Fatface",
"Aclonica"=>"Aclonica",
etc...
);
The php returned is serialized:
a:320:{
i:0;
a:3:{
s:11:"font-family";
s:32:"font-family: 'Abel', sans-serif;";
s:9:"font-name";
s:4:"Abel";
s:8:"css-name";
s:4:"Abel";
}
i:1;
a:3:{
s:11:"font-family";
s:38:"font-family: 'Abril Fatface', cursive;";
s:9:"font-name";
s:13:"Abril Fatface";
s:8:"css-name";
s:13:"Abril+Fatface";
}
etc...
How can I translate that into my array?
You can do this by unserializing the data (using unserialize()) and then iterating through it:
$fonts = array();
$contents = file_get_contents('http://phat-reaction.com/googlefonts.php?format=php');
$arr = unserialize($contents);
foreach($arr as $font)
{
$fonts[$font['css-name']] = $font['font-name'];
}
Depending on what you're using this for, it may be a good idea to cache the results so you're not fetching external data each time the script runs.
Use unserialize(): http://www.php.net/unserialize

Categories