1

A slightly different question that all the others out there... I am able to easily pass JSON from a PHP page to JavaScript using the jQuery.ajax() method, but here is my situation:

I have a set of contact data in MySQL, each with firstname, lastname, lat, lng. I have created a page that on one half displays the contact data (firstname, lastname) in tabular format. On the other half, I have a Google Map that is populated with markers from the data set (lat, lng). Now, to allow the two halves to share the same dataset, there are two methods but I am happy with neither:

  1. In the PHP file, pull the data from MySQL, use that data set for the table, then convert that data to JSON, write it out to a JavaScript variable and use that variable to populate the Google Map. Don't like doing this, as there are hundreds of data points, meaning the JSON string is very large and bloats the page, along with having all the data in human readable form in the source (I understand the data is there no matter what as in all cases it is on the client side, just more apparent here).

  2. In the PHP file, pull the data from MySQL, use that data set for the table, then in my JavaScript, make an AJAX call via jQuery.ajax() to another PHP file that generates the JSON data. Hate this as it results in two calls to the same datasource.

I am sure I am missing something obvious here, any pointers/help?

EDIT: Per option #1 above, I am well aware of how to echo out JSON from PHP to JavaScript... just unhappy with both solutions (i.e. JSON is in source, or JSON is effectively a second call to the data source).

Community
  • 1
  • 1
Unpossible
  • 10,607
  • 22
  • 75
  • 113
  • 1
    How do you do it currently? Why not build the table with JavaScript? On page load, make an Ajax call, get the data, build the table, display the points. Depending on the size of the data, you might want to use pagination anyway. Or do you display all the data in the table at once? – Felix Kling Jun 22 '11 at 13:00
  • why not build the table and the map using the json data? it'd be super easy with jQuery, but also doable with plain javascript. – Patricia Jun 22 '11 at 13:03
  • You could make one Ajax call for the JSON and use it to geneate both the table and the map. OR use javascript to traverse the table and get the info for the map from there – Greg Guida Jun 22 '11 at 13:04
  • Had thought about this, but we have a custom PHP-driven 'table' widget that we are using that supports paging, filtering, sorting, etc. Was hoping not to have to re-write that how thing in JS. – Unpossible Jun 22 '11 at 13:04
  • And this widget works with Ajax too? – Felix Kling Jun 22 '11 at 13:06
  • 'Widget' is purely server side PHP that takes a formatted data source and a few instructions, and generates the HTML for the table, controls, etc. – Unpossible Jun 22 '11 at 13:07
  • So on pagination, it makes a new call to the server and reloads the page? Why don't just store the JSON data of the elements currently in the table in the source? Or do you mean that *this* is too much data too? – Felix Kling Jun 22 '11 at 13:09
  • Well, currently the paging uses a simple LIMIT setup, so yes, it makes new calls to db when pages change, as the dataset is several thousands entries, with the possibility into the tens of thousands. Trying to avoid having MySQL have to dump all that data at once to the PHP page. – Unpossible Jun 22 '11 at 13:18
  • Building a table AND map with JavaScript can very possibly enter the realm of too much client-side code handling. It would be FAR faster to make two DB calls than count on the client to render a table of data and a map. – David Ryder Jun 22 '11 at 13:23

5 Answers5

1

Your best bet would be to enable caching on your mysql server and make two identical calls:

http://www.petefreitag.com/item/390.cfm

You can't really put data in two different places without a) making two calls to the database or b) storing the results in a .txt file (or similar) and retrieving it via ajax.

I suppose you could do b) but it seems a little sloppy and would probably create more overhead than simply making 2 DB calls.

David Ryder
  • 1,291
  • 5
  • 14
  • 27
  • I am indeed caching selects, so this may be an option. I think you meant to say "I suppose you could do a)...", in terms of writing the data out too the source, correct? – Unpossible Jun 22 '11 at 13:39
  • No I meant I think a) is IMO the best option but b) is also an option if you are strictly limiting yourself to one DB call without printing the results to the page. – David Ryder Jun 22 '11 at 14:18
1

Your requirements are self-contradicting:

  • your data is in human-readable form in a table, yet you object to send it via JSON, because it's "in human-readable form [...]"

  • the table is a huge bloat with all the tds, trs, and yet you mind sending the same data over JSON (it would probably take LESS space).

Nevertheless, if you REALLY object to JSON and do not mind the table, you can extract the data from the table (that you send anyway). Rather silly, but here goes:

<script src='http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js'></script>
<table id='test'>
    <tr>
        <td>John</td><td>Smith</td>
        <td>354.3</td><td>52.5</td>
    </tr>
    <tr>
        <td>Adam</td><td>Dreger</td>
        <td>12.3</td><td>  52      </td>
    </tr>
    <tr>
        <td>Filip</td><td>Smith</td>
        <td>354.3</td><td>7.5</td>
    </tr>
</table>
<script>
    var data = $("#test tr").map(function(){
        return [$("td", this).map(function(){
            return this.innerHTML.match(/^\s*\d+(.\d+)?\s*$/)? 
                parseFloat(this.innerHTML) : this.innerHTML;
        }).toArray()]
    })
</script>

This is the famous View Controller Model pattern, where the View is queried by the Controller to gather data to be used as a Model ;-)

A much better idea (but you are against sending JSON) would be to send the data with JSON, and generate the table with Javascript. This way you still have a clear separation between model and a view. It's not really a religious thing, but if you decide to, say, add some spans to the displayed data, you will not have to parse it.

Plenty of reasonable plugins out there will help you turn your data into table, but you might get away with:

<div id='another'>
 - - -
</div>
<script>
    // I assume that data is an array of arrays
    $('#another').html(
        [
        '<table border="1">',
        $(data).map(function(){
            return ['<tr>',
            $(this).map(function(){return "<td>" + this + "</td>"}).toArray().join("")
            ,'</tr>']
        }).toArray().join(""),
        '</table>'
        ].join("")
    );

</script>

(note: the two snippets above can be chained and result in duplicating of the first table: fun!)

EDIT:

Even data that is not displayed in the table could be put there (eg. in invisible spans) and made inaccessible for a casual copy/paster using some trivial encoding, like rot13 (not included in the answer, but widely available). Like so:

    <style>.secret {display: none}</style>

    <tr>
        <td>Adam</td><td>Dreger</td>
        <td>12.3</td><td>  52  </td>
            <td><span class='secret'>({frperg:"ovt bar"})</span></td>
    </tr>

And in the code:

<script>
    var data = $("#test tr").map(function(){
        return [$("td", this).map(function(){
            return this.innerHTML.match(/^\s*\d+(.\d+)?\s*$/)? 
                parseFloat(this.innerHTML) : this.innerHTML;
        }).toArray(), 

            eval($(".secret", this).html().rot13())]
    })
</script>
fdreger
  • 12,264
  • 1
  • 36
  • 42
  • I've hidden a few of the details... there are a number of other fields that the Google Map will use that the table will not, such as street addresses, and other similar information. This data will not be present in the table, and I'd like to keep it out of the source to stop somebody from doing a simple copy/past operation to grab it all. – Unpossible Jun 22 '11 at 13:43
  • As I metnioned in the comments above, I am working with an existing PHP-based table implementation that includes paging, filtering, sorting, etc and was hoping to avoid recreating this functionality on the client side. Certainly not against it and I agree, it's likely the best solution, but I am working within a few constraints here. – Unpossible Jun 22 '11 at 13:46
  • 1
    @Paul: frankly, "the few constraints" is logic itself. You can not send the data, and yet not send it. Have it visible, and yet invisible. A JSON service will be even easier to copy/paste, and quite tedious to protect. Anyway, you can add any data to the table, even data that is not displayed - so this is not a problem. I will edit the answer. – fdreger Jun 22 '11 at 14:05
  • +1 Yes, was trying to have the best of both world's, but as you mention, it's just not possible, have to go with one or the other. As I am stuck with the PHP table generator for now, I'll have to make the two separate calls, and then over the coming weeks, look into transitioning to a JS table. – Unpossible Jun 22 '11 at 14:24
  • @Paul: well, reading data from the table is not really that terrible... sometimes you have to sacrifice "niceness" for "workshereandnowness" :) Thanks. – fdreger Jun 22 '11 at 14:32
0

It depends on how large the data set is. If it's a big payload, you might want to source it as an external file (i.e. make an ajax request) in order to have the browser cache it. However, in most cases, minimize the number of HTTP requests as much as possible. Personally I'd go with embedding the json into HTML unless it's maybe >20 kb zipped.

sapht
  • 2,789
  • 18
  • 16
0

I would use a variation of #2. Yes, fetch the JSON via AJAX, as that will make the page load faster and will also be more flexible -- perhaps at some point in the future you'll want to be able to display the map without the table, or some such.

But add a PHP class that wraps the call to the datasource and that is used by both the page that generates the HTML and the page that generates the JSON. This will make it easier to cache the results of the query, and will eliminate duplicate code.

Jacob Mattison
  • 50,258
  • 9
  • 107
  • 126
  • So essentially something like: make call to data source from PHP, storing resulting MySQL result in memcached, then in the PHP page that listens for the Ajax call, check memcached for the same result, if not found, re-run query? – Unpossible Jun 22 '11 at 13:16
  • Yes, that seems right, although if there's formatting or other manipulation that happens to the data that is common to both types of presentation, you'd want to cache the result of that manipulation rather than caching the raw mySQL result. – Jacob Mattison Jun 22 '11 at 15:22
-2

good choice I always pass data to the client in JSON, use this command

<?php
$arr = array('a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5);

echo json_encode($arr);
?>

It's as easy as that, print the output and traverse it like any other Javascript object at the client side ;)

  • Have you read the first sentence? *"I am able to easily pass JSON from a PHP page to JavaScript using the `jQuery.ajax()` method"* . He knows how to do that. – Felix Kling Jun 22 '11 at 13:02
  • I understand how to do that, as the question indicates, I'm just not happy with exposing the entire JSON array in the page source in this way, as the JSON array will have many many entries (thousands). – Unpossible Jun 22 '11 at 13:03
  • use the JSON to populate the table and the map, this is the quickest and easiest way, don't ever make 2 http calls if you dont need to – David Tulip Jun 22 '11 at 13:05
  • The table is generated on the server side, how would I use the same JSON for both without running into problem #1 of having the complete large JSON array written out to the HTML source? – Unpossible Jun 22 '11 at 13:14
  • well it was a little confusing tbh since jQuery.ajax() is a client side method it's not used to pass anything FROM php... I'm thinking though, that if the google map is gonna be populated client side then that data is gonna have to be sent through anyway I guess u could just use php to echo out the embed code for the map already pre-populated with the coordinates data and echo out the table too both built from the same script. I really don't think it's necessary or helpful to make 2 http requests – David Tulip Jun 22 '11 at 14:07