0

Context

I'm building a WordPress Theme Template and am trying to pass an array of data from a Advanced Custom Fields > Repeater Field, using PHP and core WordPress functions, to a JavaScript / HTML5 pie chart.

The Problem

I don't know how to pass the PHP data to JS in a format JS understands.

The Questions

I'm not confident I'm asking the questions correctly, or thinking about the problem correctly. For example, I believe I can use JS to communicate directly with the database. But here's what I think the questions are:

  • How do you pass a PHP array outside of a loop and into a format readable in JS?
  • What are some links to training materials or courses on the subject?

Code

Here is my code:

<?php
if( have_rows('tpc_psmr_referrer') ):
  while ( have_rows('tpc_psmr_referrer') ) : the_row();
        $tpc_psmr_referrer_type = get_sub_field('tpc_psmr_referrer_type');
        $tpc_psmr_referrer_platform = get_sub_field('tpc_psmr_referrer_type_platform'); // This needs to get passed as an array to the JS below.
  endwhile;
endif;
?>

<script type="text/javascript">
google.charts.load('current', {'packages':['corechart']});
google.charts.setOnLoadCallback(drawChart);

function drawChart() {

  var data1 = google.visualization.arrayToDataTable([
    ['Task', 'Hours per Day'],
    ['Work',     11],
    ['Eat',      2], // This is where the PHP array needs to be output.
    ['Commute',  2],
    ['Watch TV', 2],
    ['Sleep',    7]
  ]);

  var options = {
    title: 'Revenue'
  };

  var chart1 = new google.visualization.PieChart(document.getElementById('piechart1'));

  chart1.draw(data1, options);

  var data2 = google.visualization.arrayToDataTable([
    ['Task', 'Hours per Day'],
    ['Work',     11],
    ['Eat',      2],
    ['Commute',  2],
    ['Watch TV', 2],
    ['Sleep',    7]
  ]);

  var options = {
    title: 'Budget'
  };

  var chart2 = new google.visualization.PieChart(document.getElementById('piechart2'));

  chart2.draw(data2, options);
}
</script>
Spencer Hill
  • 1,043
  • 2
  • 15
  • 38
  • Are you going to make an ajax request to your php from javascript? – David Kamer May 07 '18 at 21:56
  • use data-attributes and output the PHP variable to it (and json_encode it - http://php.net/manual/en/function.json-encode.php). You can then retrieve from JS. https://developer.mozilla.org/en-US/docs/Learn/HTML/Howto/Use_data_attributes – Ben Dubuisson May 07 '18 at 21:57
  • 1
    @BenDubuisson That's one way to do it, but I'd argue to rather put the JSON in an invisible element to avoid any chance of XSS ( https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet#RULE_.233.1_-_HTML_escape_JSON_values_in_an_HTML_context_and_read_the_data_with_JSON.parse ) – Jakub Judas May 07 '18 at 22:11
  • @JakubJudas an invisible element does not prevent from XSS – Ben Dubuisson May 07 '18 at 22:13
  • @BenDubuisson true, but it does make escaping more foolproof (example: a beginner could use single quotes in html but escape using htmlentities with default settings). But maybe I'm paranoid and I'm definitely off topic so I'll stop now. – Jakub Judas May 07 '18 at 22:28
  • @cHao that article is exclusive to variables and my question is regarding arrays. Thanks though! – Spencer Hill May 07 '18 at 22:37
  • @SpencerHill: The answer doesn't change just because your array is or isn't in a variable. – cHao May 07 '18 at 22:50

4 Answers4

0

Look at json_encode()'ing the values in your while loop, and echoing the data structure that holds them, in the PHP script. $.ajax() request the script, and parse/appropriate the JSON returned on the front end in the success callback.

More specifically, for links to more information on the mechanisms involved in the process, look at json_encode at php.net (Example 1 is straightforward):

http://php.net/manual/en/function.json-encode.php

and the jQuery API documentation on $.ajax:

http://api.jquery.com/jquery.ajax/

SCRIPT.PHP

<?php 

  header("Content-type: application/json");

  $data_array = ['one','two','three'];
  $json = json_encode($data_array);
  echo $json;

?>

JS

$('document').ready(function() {
    $.ajax({
        type:'POST',
        url:'/the/path/to/script.php',
        dataType:'JSON',
        data:{
        },
        success:function(data){
            $.each(data,function(x,y) {
                console.log(data[x]);
            });  
        },
        error:function(jqXHR,textStatus,errorThrown){
            console.log('Could not retrieve JSON');
        }

    });
});
mdlanglais
  • 351
  • 2
  • 9
0
<?php $data_array = [1,2,3...]; ?>

<html>
  <div id='yellowstone' hidden>
     <?php echo json_encode($data_array); ?>
  </div>
</html>


<script>
     var array = JSON.parse(document.getElementById('yellowstone').innerHTML);
</script>
Community
  • 1
  • 1
  • If you're doing that, might as well output it straight as a Javascript variable. `` – Ben Dubuisson May 07 '18 at 22:15
  • Unnecessarily commingling the markup, js, and php using this sort of approach. It's cleaner to request the data from a dedicated php script. – mdlanglais May 07 '18 at 22:48
  • @mdlanglais example? – Christopher Sparks May 08 '18 at 04:29
  • @Frank See my answer above, I added a basic working example. You can do what you want with the values returned in the callback at that point. This way your concerns are kept separate, js in a js file, server-side code in its own script. – mdlanglais May 08 '18 at 21:40
0

WordPress has a function called wp_localize_script. It allows you to pass an array to your script and then access it in your JS as an object.
For example:

wp_localize_script( 'your_script', 'your_script_data',
    array( 
        'ajax_url' => admin_url( 'admin-ajax.php' ),
        'var_1' => 'value 1',
        'var_2' => 'value 2',
    )
);

Then somewhere in your JS

alert(your_script_data.var_1)

will display value 1

P.S. ajax_url contains and URL to make your AJAX calls in case you need that too. Here is some explanation on that.

Igor Yavych
  • 4,166
  • 3
  • 21
  • 42
  • Thanks, this seems like it could work but a couple clarifying questions: The docs state the model for wp_localize_script are `wp_localize_script( string $handle, string $object_name, array $l10n )` but your model suggests handle to become my script path? And localization be my array. So it seems like that would output an error. – Spencer Hill May 07 '18 at 22:34
  • @SpencerHill that's exactly how it works. There won't be any error. Handle is the name you gave your script when you enqueued it (1st parameter of `wp_enqueue_script`) and yes, localization is in fact your array. – Igor Yavych May 08 '18 at 07:34
0

I think you need something like this:

<?php
$php_var = [['Task', 'Hours per Day'],
    ['Work',     11],
    ['Eat',      2], 
    ['Commute',  2],
    ['Watch TV', 2],
    ['Sleep',    7]];
?>


<script type="text/javascript">
    var data = <?= json_encode($php_var, JSON_HEX_TAG) . ';' ?>   
</script>

See this PHPFiddle.

Other usefull links:

how-to-pass-variables-and-data-from-php-to-javascript

pass-a-php-array-to-a-javascript-function

ernesthm
  • 421
  • 4
  • 15
  • Why did you use JSON_HEX_TAG? The docs on that state that's for replacing < and > with their unicode value. – Spencer Hill May 07 '18 at 22:31
  • 1
    Yes, I used JSON_HEX_TAG for security issues, because passing in a raw string to JSON encode can lead to XSS attacks. See https://stackoverflow.com/questions/6816787/json-php-to-javascript-safe-or-not/6817147#6817147 . – ernesthm May 07 '18 at 22:49