I have a <select> element that I need to populate with values I get from an Ajax call. I am debating whether to have the Ajax return a proper JSON object of keys/values or just have it echo out a bunch of <option> elements. The options need to be displayed in an alphabetical order in the select.
I feel like using a JSON object is the proper way of doing it. But when that object is returned, I have to go through the process of sorting the JSON object by name instead of value. For example:
My PHP returns the following JSON Object response:
{"21":"Bandana","18":"Baseball","19":"Cowboy","20":"Trucker"}
That is the proper order that I want the items to be displayed in the <select> element. But when the Ajax callback gets the JSON Object, it's sorted by key instead of value:
{"18":"Baseball","19":"Cowboy","20":"Trucker","21":"Bandana"}
So iterating through this JSON object and appending <option>'s to the <select> will result in the values not being alphabetical. So now, I have to go through the process of sorting this before using it.
Alternatively, if I just throw out the JSON object altogether and just had my PHP do this:
foreach ( $array as $key => $value )
echo "<option value='$key'>$value</option>";
Now, back in my Ajax callback all I have to do is append the output to my <select> and I'm good to go. Everything is sorted and it works perfectly.
So in the end, I feel like JSON is the proper way to do it, but you have to jump through several more hoops to get to the goal. Are there easy JSON Object tricks I'm unaware of? Why would I ever use a JSON Object in this situation if I have to reformat the data in the callback?
Use a JSON array instead of an object.
[{"key": "21", "value":"Bandana"},{"key":"18", "value":"Baseball"},{"key": "19", "value":"Cowboy"},{"key":"20","value":"Trucker"}]
Property names of an object aren't maintained in any particular order. That is, when you iterate through the property names of an object with a JavaScript for ... in loop, the order is not defined. The runtime system can give you the names in any order; I don't think it's necessarily even repeatable.
I would prefer json with array of arrays. First element as key and second as value.
[[21,"Bandana"],[18,"Baseball],[19,"Cowboy"],[20,"Trucker"]]
Related
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
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);
So im trying to figure out the best way to get MySql table data into either a multidimensional PHP array or convert that multidimensional array into a json string.
Essentially what im trying to do is have a php include that returns the JSON string so i can iterate through it. I am needing a single key with multiple values, so im not 100% sure that im headed in the right direction.
I want to assign multiple values to the same key, for example:
[{"key1": "package1", "package2", "package3"}, {"key2": "package1", "package2", "package3", "package4"}]
I think that is not going to work right? Because i dont have any type of index's?
That is not valid JSON. The structure you are looking for would be something like:
[
{"key1": ["package1", "package2", "package3"]},
{"key2": ["package1", "package2", "package3", "package4"}]
^ An array as the value to the key "key1", "key2", etc..
]
At the PHP side, you would need something like:
For every row fetched from MySQL
$arr[$key] = <new array>
for each package:
append package to $arr[$key]
echo out json_encode($arr)
JS arrays have an implicit array keying, starting at index 0. What you've got is a perfectly valid JS array, the equivalent of having written:
var x = []; // create new empty array
x[0] = {"key1": .... }; // first object
x[1] = {"key2": ....} // second object
Note that the contents of your {} sub-objects is NOT valid.
You should never EVER built a JSON string by hand. It's too unreliable and easy to mess up. It's just easier to use a native data structure (php arrays/objects), then json_encode() them. Ditto on the other end of the process - don't decode the string manually. Convert to a native data structure (e.g. json_decode(), JSON.parse()) and then deal with the native structure directly.
essentially, JSON is a transmission format, not a manipulation format.
I have a multidiminsional array that I have created in php that is passed back to a jQuery script. I need to iterate through this array and process the data.
In Firebug I can see that the data is located at data.data.items. I've tried finding the length of the array using data.data.items.length, but it comes back as undefined. Interestingly, this worked prior to my php portion working correctly when it passed back an array of 8 empty items. Now that it's populated (and the indexes are strings), length doesn't work. There is also an object in each of the items. What's breaking this?
An Array in JavaScript is an object nonetheless. When setting values using strings (or anything that isn't an integer), you are actually setting a property of the object (you are actually doing this when setting it with integer keys as well, but it's handled slightly differently).
To the issue of its sudden breakage after using strings as keys, I would expect that PHP realizes when you have an honest-to-goodness array versus an associative array, thus it sends arrays (surrounded by []) when all keys are integers, and objects (surrounded by {}) otherwise. I believe in the string-keyed case, PHP is generating objects, and thus .length becomes undefined (rather than 0 as in an empty array).
To answer your question, there is a simple way to count the "length" of this data:
var i = 0;
for (var item in data.data.items) {
i++;
}
Which will iterate through each property of data.data.items and count them. Note that if you (or any library you include) adds a property to the Object prototype, this will not produce expected results. This is fairly uncommon, but you must be aware of it when using for..in.
You can address this by using the method Nagh suggested, which ignores properties not defined on that particular object:
var i = 0;
for (var item in data.data.items) {
if(data.data.items.hasOwnProperty(item)) {
i++;
}
}
You can always use "foreach" kind of loop. In this case, you don't need to know what array length is there or even is it array or not, since you can iterate over object properties aswell.
As Joe already has pointed, javascript doesn't have associative arrays and when you trying to use one - you end up with object with properties. However, if u sure, that only properties this object got - is your array you can use code like that:
for (i in arr) {
if (arr.hasOwnProperty(i)) {
//do something with arr[i]
}
}
However if you really need an array, consider using integer as an array index.
In PHP I'm running a mysql_query that has an ORDER BY clause. I'm then iterating through the results to build an associative array, with the row_id as the key.
Then, I'm calling json_encode on that array and outputting the result.
This page is loaded with AJAX, and defined in a Javascript variable. When I iterate through that Javascript variable, will I still have the order that was returned from the mysql_query?
PHP arrays are somewhat unique in their property of maintaining insertion order. Javascript doesn't have associative arrays per se. It has objects, which are often used as associative arrays. These do not guarantee any particular key order.
Why not output them as an array? That will have a particular order. If you want some sort of key lookup why does the order matter?
What cletus says is correct, but in my experience, most browsers will maintain the order. That being said, you should consider using an Array. If you need to sort it once you receive it on the client-side, just use the .sort() function in JavaScript:
rows.sort(function(a, b) {
return a.row_id - b.row_id;
}
Though it seems like it works, the order of properties in an object can't be counted on. See the many comments below for more info (smarter eyes than mine). However, this was the code I used to test the behavior in my own limited testing:
var test = {
one: 'blah',
two: 'foo',
another: 'bar'
};
for (prop in test) {
document.write(prop + "<br />");
}
Prints (in Firefox 3.6.3 and Chrome 5.0.375.9):
one
two
another
Also, you may want to be sure you're getting the type of JSON encoding you're needing back from json_encode(), such as an object (uses {} curly braces) and not an array ([] braces). You may need to pass JSON_FORCE_OBJECT to json_encode() to force it.
Edited to clarify that the Array approach is preferred)
Edited again (sorry), as I had overlooked pcorcoran's comment, which has a link to an issue in Chromium's issue tracker regarding this. Suffice to say, the order an object's properties is not reliable.