1

I am pulling an array from a mysql database. A pretty simple select statement that then gets put into your run-of-the-mill multi-dimension array (rows and columns) to generate some HTML. So far so good.

I want to be able to store that array somewhere (DOM?) on the client-side so that clients can re-use and manipulate that data (via jQuery) without having to re-query the database for the same data each time.

So... lets say my php array is:

$fruits = array ( "fruits"  => array ( "a" => "orange",
                                       "b" => "banana",
                                       "c" => "apple"
                                     ),
                  "numbers" => array ( 1,
                                       2,
                                       3,
                                       4,
                                       5,
                                       6
                                     ),
                  "holes"   => array (      "first",
                                       5 => "second",
                                            "third"
                                     )
                );

How do I store $fruits on the client-side so I can re-use the data on command via javascript?

Your Common Sense
  • 156,878
  • 40
  • 214
  • 345
themerlinproject
  • 3,542
  • 5
  • 37
  • 55

4 Answers4

5

Serialize $fruits into JSON with json_encode, then write it to something like a hidden input. Using jQuery you can query the DOM for the input and $.parseJSON its value.

Server side:

<input type="hidden" id="FruitData" value="<?php echo htmlentities( json_encode( $fruits ) );?>" />

Client side:

var fruits = $.parseJSON( $( '#FruitData' ).val() );

You could put it anywhere you like, really--I just prefer an input. Inputs are handy for shipping the data back to the server too (via methods other than AJAX, even). Cookies would work too. I do avoid outputting directly into a script block though. I don't like how my syntax editor freaks out on PHP inside the JS, it often leads to a lot of globalized code, and it gets in my way when it comes time to move the script to an external file.

Also, as long as you're providing the JSON API to older browsers, you could replace $.parseJSON with JSON.parse.

JAAulde
  • 19,250
  • 5
  • 52
  • 63
  • Thanks, is there any reason to use $.parseJSON over JSON.parse or is it ALWAYS better to use JSON.parse? – themerlinproject Apr 06 '11 at 04:49
  • 1
    +1 While I'm not a fan of using an attribute for this, this is *the only answer posted* (including mine) which doesn't suffer from valid JSON breaking the HTML or Javascript. –  Apr 06 '11 at 07:05
  • The string will be HTML-escaped, not JS-escaped as desired. If PHP has a value = `<`, JS will see that as `<` rather than '<'. Will need one more run over the string to replace all such instances. – UltraInstinct Apr 06 '11 at 07:45
  • @Thrustmaster The "&" transformations happen to the document is read. (HTML has a special exclusion for the –  Apr 06 '11 at 17:11
4

How about storing it as a simple javascript object? Something like the folllowing:

//yourphpfile.php
<script type="text/javascript">
var obj = JSON.parse('<?php echo json_encode($my_arr,JSON_HEX_TAG|JSON_HEX_APOS); ?>');
console.log(obj);
</script>

The client side will have the entire data into the obj object.

UltraInstinct
  • 43,308
  • 12
  • 81
  • 104
  • 1
    If you remove the double quotes from around the PHP output, you could do without the call to JSON.parse. I prefer never to have PHP outputting in JS blocks, though. It just gets in my way when I am ready to move the script to an external file. – JAAulde Apr 06 '11 at 04:23
  • Thanks, but I'm curious about the re-usability of this? This is a simple approach, but it seems that the other answers use this in conjunction with a hidden div or input field on page, whereas you don't. – themerlinproject Apr 06 '11 at 04:23
  • @JAAulde: Yes, but `JSON.parse` is surely a **safe** way of doing it. What if the PHP response is modified by my evil (:P) colleague to something like `{"a":"b"}; doSignOut();` :-) @themerlinproject: It sure is reusable. You can use this the exact same way you do with other approaches using hidden div/input, provided you refer to it properly. – UltraInstinct Apr 06 '11 at 04:28
  • @Thrustmaster Yeah, I see what you're saying about script injection. A valid point, indeed. – JAAulde Apr 06 '11 at 04:30
  • As I see you accepted this answer, I recommend you to read the remark in my answer about providing the JSON API to older browsers (IE <8) which do not provide it natively. – JAAulde Apr 06 '11 at 04:37
  • @themerlinproject Then the axioms about the code are wrong anyway -- e.g. what if happens? What if the ? What if a ? I believe that only the correct JSON (as a JS literal -- not a string!) should be emitted here. –  Apr 06 '11 at 04:41
  • @pst - could you be a bit more specific? What is the correct JSON that you are referring to? – themerlinproject Apr 06 '11 at 04:48
  • `var obj = );` This also fixes a [potential] bug with the "suggested" answer. Imagine if the JSON contained " characters. The resulting JavaScript would have been invalid: `JSON.Parse("{"hello": "world"}")` I am holding off on a -1, but **this answer is no good as it is**. If json_encode ever does *not* return valid JSON, then json_encode is broken and should not be used. –  Apr 06 '11 at 04:51
  • @pst: Ideally, that `JSON.parse` statement would go into a `try` block. In case its an invalid JSON string, you would have to catch that exception. I just gave an idea up there, never the entire code. BTW, whats the harm in being on the safer side? I prefer to use JSON.parse than the way suggested by JAAulde (much more than a matter of preference,though). You are free to use it the way you want, provided you are absolutely sure of what gets emitted from the PHP. In this case, the OP *can*. I seriously hope he has no such colleague, as I once had! :-) – UltraInstinct Apr 06 '11 at 05:09
  • It doesn't matter. Please see above. There is no reason for a try. The code in this answer MAY CAUSE THE JAVASCRIPT TO BE INVALID FOR VALID JSON as shown. `{"hello": "world"}` is valid JSON (and thus a valid JS expression). `"{"hello": "world"}"` is not a valid JS expression. A `try` would not change this. Please look at the HTML (and invalid JavaScript) this answers generates. The other answer from JAAulde is immune to this flaw because the value is read from an element in the DOM. The other answer also has a flaw in it. (I will post a comment on it as well.) –  Apr 06 '11 at 06:57
  • Yes, I didn't really notice that double quotes thingy. I have edited my answer. You can check that out! – UltraInstinct Apr 06 '11 at 07:40
  • @Thrustmaster This is still not correct as JSON can contain the ' character :( `['hi, susasn']` As pointed out in my answer (which also contains a flaw), it's not an easy issue to deal with. –  Apr 06 '11 at 17:04
  • @pst: Check the code again. I have added optional arguments to `json_encode(.., JSON_HEX_APOS)`, which will escape out `'` also. And BTW, I am not on my system to try that out; I am just sure(or hope) it works. I have never used JSON_HEX_APOS before, though! :-) – UltraInstinct Apr 06 '11 at 17:21
  • @Thrustmaster Much better and a +1! (I have been educated about the json_encode options as well!) Please note that *both* JSON_HEX_APOS *and* JSON_HEX_TAG are required (without JSON_HEX_TAG it is possible for the JSON to encode which would caused malformed HTML). I still would not recommend using this secondary parse step, but I do not know of any issues with the above solution as it is. –  Apr 06 '11 at 20:42
1

One approach, and one that we (our company) has used before, is to echo that data as JSON in a hidden div on the page. Then use a combination of jQuery's .text() method and JSON.parse() to get the data as JSON on the client side.

Something like this:

echo "<div id = 'fruits' style = 'display:none;'>".json_encode($fruits)."</div>";

Then in Javascript:

var fruits = JSON.parse($("#fruits").text());

console.log(fruits.fruits.a); // orange 
Alex
  • 64,178
  • 48
  • 151
  • 180
  • 1
    -1 This is not correct. JSON can contain characters such as "<", ">" and "&" (in string literals) which could break this. –  Apr 06 '11 at 07:05
0

Actually, there is an issue with this and being "unsafe" (but I leave this reply for reference as well as exposing the flaw I didn't consider earlier):

If '</script>' appears in the output of the JSON (which is perfectly legal) then the HTML is invalid.

EDIT: json_encode takes the optional JSON_HEX_TAG which will prevent the above situation from occurring. Be sure to use the correct output escapes as required for context.


(And previous stuff...)

I am going to prose the same answer as everyone else...

...use json_encode or a similar/better JSON encoding mechanism. This should result in the JSON -- JSON is a text representation of a subset of JavaScript object literals. This JSON is then (unless json_encode is broken) guaranteed to be a 100% valid side-effect-free expression in JavaScript.

...with one exception: just use the-valid-JS-expression as-is.

# Look, no added nonsense.
var blah = <?= json_encode($my_arr); ?>;

It is very unlikely that the JSON will have to be shoved into an element property before use with a good design. (E.g. likely no need for any "parsing" from a stored value; utilize JavaScript and the execution order between the back-end and front-end in emitting code.)

Please take the time to think about the different stages the processing occurs in. For instance, the following is wrong:

var blah = ParseJson("<?= json_encode($my_arr); ?>;")

It is wrong because after PHP is run the resultant HTML returned to the browser may be:

var blah = ParseJson("{"hello": "world"}")

Happy coding

  • While `json_encode` is trustworthy, I believe Thrustmaster is worried about someone who may or may not know what they're doing removing the `json_encode` and adding damaging code by any number of nefarious or accidental means. While the likelihood of that is low, and the same argument could be made of almost anything being output to the client, it is something that should (at the very least) be in a developers mind. So while not a giant concern, I believe his point is valid. Anyway, your answer is also quite valid--though as I stated in detail in my own answer, I keep PHP out of my scripts. – JAAulde Apr 06 '11 at 11:09
  • @JAAulde Doesn't make a difference for the other reason posted. After writing my answer I realized that some assumptions I had about JSON generation and just "putting it in a Javascript block" are invalid, as hinted in the update to the top. None of these answers is valid outside of the small area for which the be behavior is well-defined. –  Apr 06 '11 at 17:06