Accessing PHP objects using both naming with reserved characters (-,#) and indexes (0) - php

In PHP figured out how to use {name-with-reserved-chars} notation to access object data after JSON decode but I also have index values as well in the path (like [0]). My attempts to add the index value has returned nothing despite all my attempts to vary the pattern. Here is an example based on a big JSON object:
["ops:world-patent-data"]["exchange-documents"]["exchange-document"]
[0]["bibliographic-data"]["publication-reference"]["document-id"][0].date.$
my attempt gets nothing:
print $result->{'ops:world-patent-data'}->{'exchange-documents'}->{'exchange-document'}->
{0}->{'bibliographic-data'}->{'publication-reference'}->{'document-id'}->{0}->date;
wondering how to place the 0 and 1 indexes in the path ...

When deserializing an actual JSON list (i.e, not an object but an actual array with numerical indices; something like [1,2,3,...] or also [{...},{...},...]), PHP's parse_json function builds a corresponding PHP array with numerical indices (while on the other hands, it maps JSON objects to instances of the stdClass class -- unless you use the $assoc parameter of the parse_json function).
So, because you are accessing arrays instead of objects, your code would probably have to look like this:
print $result->{'ops:world-patent-data'}->{'exchange-documents'}->
{'exchange-document'}[0]->{'bibliographic-data'}->{'publication-reference'}->
{'document-id'}[0]->date;
It would probably easier to use the $assoc parameter, forcing json_decode to map the entire JSON object with associative arrays, allowing you to use the square bracket notation for object access also.

Related

PHP confusing Object with Array after parsing JSON data

having parsed an object of nested objects and nested arrays PHP is mixing them up. it works well on some objects but not on others
$f = json_decode($jsonObject, true);
example of nested objects that php recognises as objects:
examples of arrays which php recognises as objects in arrays:
examples of object which php recognises as an arrays:
if i begin mixing arrays of objects it no longer recognises simple objects, it interprets them as arrays.
how can i get php to fully recognise arrays and objects in JSON,
You can turn php objects or arrays into json with json_encode()
They will come out as an array or an object depending on whether you set the extra flag when decoding. json_decode($jsonstr,true) will return an array, json_decode($jsonstr) will return an object.
It doesn't matter whether the data was an object or an array before it went in, it only matters how you decode it.
Your code above will always return an array regardless of whether you encode an object or an array.

Why does Laravel store two different array syntaxes in databases and which one is correct?

I come from a Javascript and Ruby background and this is baffling me. Laravel can store two different array syntaxes in my DB depending on how I handle my array serialization. In my understanding, collect() creates a true Laravel array. Why then is it storing a serialized array? Furthermore, is the {'key':'value'}syntax still an array despite having no square brackets surrounding it? It looks to me like a standard object or a hash, but if I try to do toArray() on it, it recognizes that it's already an array and throws an error. What am I misunderstanding and what is correct here?
Given a form:
edit.blade:
<select class="form-control m-bootstrap-select m_selectpicker" name="temp">
<option value={{ json_encode(array("$key"=>"$cph"), JSON_FORCE_OBJECT) }}>
</select>
The following two controllers syntaxes yield different database insertions.
PageController.php:
$page->cph_default = collect($request->temp);
$page->save();
Laravel stores an array with the following syntax in my database: ["{\"11\":\"1100\"}"]
PageController.php
$page->cph_default = json_decode($request->temp, true);
$page->save();
Laravel stores an array with the following syntax in my database: {"19": "1900"}
A PHP array with the syntax ['key' => 'value'] is called an associative array, and acts like a hash. A JSON-encoded associative array will show up as an object in JSON syntax. Examples and more info on PHP.net
Laravel's collect() function is a convenience wrapper for creating a new Collection. A Collection is not really a "true Laravel array" so much as it is an object wrapper with some convenience methods for modifying the underlying array. Think of it like a scalar object.
In your form when generating the option value, the submitted form value ($request->temp) will be a JSON-encoded string. Literally the string '{"19": "1900"}'.
Calling collect($request->temp) does no modification to that submitted data. It's simply creating a new Collection (array), containing a single string item. If you were to call toArray() on the collection, you'd see something like this:
[
0 => '{"19": "1900"}'
]
Note that this is not an associative array, it is a numeric array with a zero-based index. This array is encoded as a JSON array, not as a hash object. Hence your first result.
Calling json_decode($request->temp) is turning the string back into an associative array (hash) before saving it via Eloquent. Eloquent then calls json_encode() again internally, turning it back into the same JSON as your form's option value.
If you were to decode the form value before creating the collection, the resulting database save would look identical. You'd just have the convenience of the Collection wrapper:
$page->cph_default = collect(json_decode($request->temp, true));
$page->save();
If you're treating the column as a JSON type, you should ensure the data passed to Eloquent is NOT already encoded, or you'll get the double encoding experienced in your first example.
No Matter What is.
First If you are stroring the array into database convert to JSON FORMAT
For eg
$variable = json_encode($request->controlname);
This is the right way to store array
Into database

Print value from stdClass Object/array with curly brackets

Using PHP, I printed out an array ($result) using print_r. But the format in which the array has been returned is a new one on me. Specifically, how do I retrieve the text found in the field "reviews_review" ("Wow, what a great...") when it's found in this particular format with its multiple values? Example:
stdClass Object
(
[node_reviews_nid] => 5270
[reviews_review] => a:2:{s:5:"value";s:38:"Wow, what a great place. The bestest!";s:6:"format";s:13:"filtered_html";}
Those extra values and curly brackets have got me stumped. If I wanted the node_reviews_nid I could simply use $result->node_reviews_nid" - but doing that to get reviews_review just retrieves too much ie,
a:2:{s:5:"value";s:38:"Wow, what a great place. The bestest!";s:6:"format";s:13:"filtered_html";})
The odd curly brackets you're seeing are the result of PHP's serialize function.
Basically it's intended to convert complex structures like objects, nested arrays and so on into simple strings which are easier and safer to transfer, for example over HTTP. Think of it as JSON representation, but specific to PHP (do not attempt to json_decode() a serialized value).
Also worth noting is that serialize-d string has a maximum length, beyond which it's simply truncated, so avoid using it for very large structures - you'll lose data.
The reverse of that is unserialize. So to read the review's text, you would first have to unserialize the "reviews_review" property, then reference the "value" index of the resulting array.
$review_data = unserialize($result->reviews_review);
$review_text = $review_data['value'];
print($review_text);
The data in reviews_review looks like a serialized array i.e. written using the serialize() function
So you will need to unserialize it using unserialize() before you can use it
$review = unserialize($obj->reviews_review);
print_r($review);

JSON_ENCODE of multidimensional array giving different results

When doing a json_encode a multidimensional array in PHP, I'm noticing a different output simply by naming one of the arrays, as opposed to not naming them. For Example:
$arrytest = array(array('a'=>1, 'b'=>2),array('c'=>3),array('d'=>4));
json_encode($arrytest)
gives a single array of multiple json objects
[{"a":1,"b":2},{"c":3},{"d":4}];
whereas simply assigning a name to the middle array
$arrytest = array(array('a'=>1, 'b'=>2),"secondarray"=>array('c'=>3),array('d'=>4));
json_encode($arrytest)
creates a single json object with multiple json objects inside
{"0":{"a":1,"b":2},"secondarray":{"c":3},"1":{"d":4}};
why would the 1st option not return the same reasults as the 2nd execpt with "1" in place of "secondarray"
In JSON, arrays [] only every have numeric keys, whereas objects {} have string properties. The inclusion of a array key in your second example forces the entire outer structure to be an object by necessity. The inner objects of both examples are made as objects because of the inclusion of string keys a,b,c,d.
If you were to use the JSON_FORCE_OBJECT option on the first example, you should get back a similar structure to the second, with the outer structure an object rather than an array. Without specifying that you want it as an object, the absence of string keys in the outer array causes PHP to assume it is to be encoded as the equivalent array structure in JSON.
$arrytest = array(array('a'=>1, 'b'=>2),array('c'=>3),array('d'=>4));
// Force the outer structure into an object rather than array
echo json_encode($arrytest , JSON_FORCE_OBJECT);
// {"0":{"a":1,"b":2},"1":{"c":3},"2":{"d":4}}
Arrays with continuous numerical keys are encoded as JSON arrays. That's just how it is. Why? Because it makes sense.
Since the keys can be expressed implicitly through the array encoding, there is no reason to explicitly encoded them as object keys.
See all the examples in the json_encode documentation.
At the first option you only have numeric indexes (0, 1 and 2). Although they are not explicitly declared, php automatically creates them.
At the second option, you declare one of the indexes as an string and this makes PHP internally transform all indexes to string.
When you json encode the first array, it's not necessary to show the integers in the generated json string because any decoder should be able to "guess" that they are 0, 1 and 2.
But in the second array, this is necessary, as the decoder must know the key value in your array.
It's pretty simple. No indexes declared in array? Them they are 0, 1, 2, 3 and so on.
output of this as in json form is year1{a,b},year2{c}, year3{d}
**a has value 1 ,b=2,c=3,d=4 stored in array of year1's a,b years2's c and years3's d respectivily
$array1 = array('a'=>1, 'b'=>2);
$array2 = array('c'=>3);
$array3 = array('d'=>4)
$form = array("year1" =>$array1,
"year2" =>$array2,
"year3" =>$array3,
);
$data = json_encode($form);

Is json_decode in PHP guaranteed to preserve ordering of elements when returning an array?

You can pass a boolean to json_decode to return an array instead of an object
json_decode('{"foo", "bar", "baz"}', true); // array(0 => 'foo', 1 => 'bar', 2 => 'baz')
My question is this. When parsing object literals, does this guarantee that the ordering of the items will be preserved? I know JSON object properties aren't ordered, but PHP arrays are. I can't find anywhere in the PHP manual where this is addressed explicitly. It probably pays to err on the side of caution, but I would like to avoid including some kind of "index" sub-property if possible.
Wouldn't it make more sense in this case to use an array when you pass the JSON to PHP. If you don't have any object keys in the JSON (which become associative array keys in PHP), just send it as an array. That way you will be guaranteed they will be in the same order in PHP as in javascript.
json_decode('{["foo", "bar", "baz"]}');
json_decode('["foo", "bar", "baz"]'); //I think this would work
If you need associative arrays (which is why you are passing the second argument as true), you will have to come up with some way to maintain their order when passing. You will pry have to do some post-processing on the resulting array after you decode it to format it how you want it.
$json = '{[ {"key" : "val"}, {"key" : "val"} ]}';
json_decode($json, true);
Personally, I've never trusted any system to return an exact order unless that order is specifically defined. If you really need an order, then use a dictionary aka 2dimension array and assigned a place value (0,1,2,3...) to each value in the list.
If you apply this rule to everything, you'll never have to worry about the delivery/storage of that array, be it XML, JSON or a database.
Remember, just because something happens to work a certain way, doesn't mean it does so intentionally. It's akin to thinking rows in a database have an order, when in fact they don't unless you use an ORDER BY clause. It's unsafe to think ID 1 always comes before ID 2 in a SELECT.
I've used json_decode() some times, and the results order was kept intact with PHP client apps. But with Python for instance it does not preserve the order.
One way to be reassured is to test it over with multiple examples.
Lacking an explicit statement I'd say, by definition, no explicit order will be preserved.
My primary line of thought it what order, exactly, would this be preserving? The json_decode function takes a string representation of a javascript object literal as it's argument, and then returns either an object or an array. The function's input (object literal as string) has no explicit ordering, which means there's no clear order for the json_decode function to maintain.

Categories