3

I have the following bit of code that draws graphs, in a loop, using google.visualisation based on values from a SQL table which I store in 3 arrays(i.e. $TotalView, $TotalFemaleView and $TotalMaleView) in the PHP portion. I use json_encode(referred this link) so I can use these arrays in JavaScript. But I am unable to access the array elements to draw the graphs. I have tried displaying the values of the arrays and they are correct.

<?php
$servername = "localhost";
$username = "root";
$password = "root123";
$dbname = "test";

$AdName=[];
$TotalView=[];
$TotalMaleView=[];
$TotalFemaleView=[];
$rowcount=0;

// Create connection
$con = mysqli_connect($servername, $username, $password, $dbname);
// Check connection
if ($con->connect_error) {
    die("Connection failed: " . $con->connect_error);
} 

$result=mysqli_query($con,"SELECT `Ad Name`,`Total View Count`, `Total Female Viewers`, `Total Male Viewers` FROM `addata` WHERE `Disp Id`=1");

$rowcount=mysqli_num_rows($result);

if(!$result) {
      die('Could not get data: ' . mysql_error());
    }
    // output data of each row 
    for($x = 0; $x < $rowcount; $x++)
    {
        $row = $result->fetch_assoc();
        $TotalView[$x]=$row["Total View Count"];
        $TotalFemaleView[$x]=$row["Total Female Viewers"];
        $TotalMaleView[$x]=$row["Total Male Viewers"];
        $AdName[$x]=$row["Ad Name"];
    }

$con->close();
?>
<html>
  <body>

    <script src="https://www.gstatic.com/charts/loader.js"></script>
    <ul id="stats"></ul>
    <script type="text/javascript">

    var array1 = <?php echo json_encode($TotalView);?>;
    var array2 = <?php echo json_encode($TotalFemaleView);?>;
    var array3 = <?php echo json_encode($TotalMaleView);?>;
    var array4 = <?php echo json_encode($AdName);?>;

    google.charts.load('current', 
    { callback: function () 
        {   
            for ( y = 0; y < <?php echo $rowcount ?>; y++) 
            {

                var data = new google.visualization.DataTable();
                data.addColumn('string', 'list');
                data.addColumn('number', 'Viewers');
                data.addRows([ 
                                ['TotalViewers',array1[y]],
                                ['Female Viewers', array2[y]],
                                ['Male Viewers', array3[y]]
                            ]);
                var options = {title:array4[y],width:400,height:300};

                var container = document.getElementById('stats').appendChild(document.createElement('div'));
                var chart = new google.visualization.ColumnChart(container);
                chart.draw(data, options);
            }
        },
        packages: ['corechart']
    });

</script>
  </body>

</html>

Can anyone point me towards the right direction?

Community
  • 1
  • 1

2 Answers2

1

Okay, I solved it. Had to pass the arrays in the eval() function before using them in the google.visualization function.

google.charts.load('current', 
        { callback: function () 
            {   
                for ( y = 0; y < <?php echo $rowcount ?>; y++) 
                {
                    array1[y]=eval(array1[y]);  
                    array2[y]=eval(array2[y]);  
                    array3[y]=eval(array3[y]);  

                    var data = new google.visualization.DataTable();
                    data.addColumn('string', 'list');
                    data.addColumn('number', 'Viewers');
                    data.addRows([ 
                                    ['TotalViewers',array1[y]],
                                    ['Female Viewers', array2[y]],
                                    ['Male Viewers', array3[y]]
                                ]);
                    var options = {title:array4[y],width:400,height:300};

                    var container = document.getElementById('stats').appendChild(document.createElement('div'));
                    var chart = new google.visualization.ColumnChart(container);
                    chart.draw(data, options);
                }
            },
            packages: ['corechart']
        });

EDIT:

I found what was causing the problem and a better solution to the eval().

The json_encode was storing the elements as strings in the arrays(as you can see from my source here).

According to this, it is a PHP version specific problem and there are a couple of workarounds:

  • Adding the flag JSON_NUMERIC_CHECK to the json_encode function. So in my case, it will be: var array1 = <?php echo json_encode($TotalView,JSON_NUMERIC_CHECK);?>. But this, according to some of the comments, is unreliable in certain cases.
  • Another solution is fixing it in the PHP section while reading the database elements from the database. $TotalView[$x]=(int)$row['Total View Count']. So this stores the database element, Total View Count as an integer in the TotalView array.
Community
  • 1
  • 1
1

Based on the information in your comments and updated PHP code, it seems that your data returned from the database queries has numbers in the form of strings. Before using eval() or the Javascript Number object, if you looked in the browser console then you might have seen errors like this:

Uncaught Error: Type mismatch. Value 12 does not match type number in column index 1

There are multiple options to resolve this (without using eval()):

  • Type cast the values as an integer or float when adding to the output arrays in PHP

    $TotalView[$x] = (float)$row["Total View Count"];
    
  • use the JSON_NUMERIC_CHECK flag with json_encode (see this answer for more info).

    var array1 = <?php echo json_encode($TotalView, JSON_NUMERIC_CHECK );?>;
    

    But beware there are drawbacks to using that constant (see this article for an example).

See this updated phpfiddle. As you can see, I created a class to simulate the database query (since I don't have a database connection in that sandbox) but allows to have the same array creation.

Please run that fiddle, and inspect the output in the browser console. Notice how the results of json_encode() produce valid arrays in Javascript, like:

var array1 = [12,10,6];
var array2 = [8,4,1];
var array3 = [4,6,5];
var array4 = ["Audi","BMW","Suzuki"];

Interestingly, the unordered list tag (i.e. <ul id="stats">), which is considered flow content, is added to the head tag in your sample code. The head tag only allows meta-data content. Move that unordered list tag to the body tag.

See the output demonstrated in the snippet below.

var array1 = [22, 16, 35, 11];
var array2 = [10, 3, 4, 9];
var array3 = [12, 13, 31, 2];

google.charts.load('current', {
  callback: function() {
    for (var y = 0; y < array1.length; y++) {

      var data = new google.visualization.DataTable();
      data.addColumn('string', 'list');
      data.addColumn('number', 'Viewers');
      data.addRows([
        ['TotalViewers', array1[y]],
        ['Female Viewers', array2[y]],
        ['Male Viewers', array3[y]]
      ]);
      var options = {
        title: 'Ad 1',
        width: 400,
        height: 300
      };
      var container = document.getElementById('stats').appendChild(document.createElement('div'));
      var chart = new google.visualization.ColumnChart(container);
      chart.draw(data, options);
    }
  },
  packages: ['corechart']
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<ul id="stats"></ul>
Community
  • 1
  • 1
Sᴀᴍ Onᴇᴌᴀ
  • 8,218
  • 8
  • 36
  • 58
  • I appreciate you taking time out for this but please forgive my ignorance because I still don't see what I'm doing wrong! I'm pretty sure the SQL statements I have are right and apart from that my array creation and javascript statements also seem to be what you've used but it still doesn't display the graphs without the eval function. – Abhijith Bagepalli Apr 12 '17 at 05:49
  • I would like to see the entire HTML/JS output from the PHP... If you don't have a public URL on the internet, could you copy and paste it somewhere like [pastebin.com](https://pastebin.com)? – Sᴀᴍ Onᴇᴌᴀ Apr 12 '17 at 06:01
  • do you mean the values of array1, array2 array3? – Abhijith Bagepalli Apr 12 '17 at 06:57
  • i mean the whole source. View the page in your browser, view the source, copy it all and paste it into pastebin - like I did in [this paste](https://pastebin.com/T0Jd5kwS)... – Sᴀᴍ Onᴇᴌᴀ Apr 12 '17 at 13:46
  • https://pastebin.com/NkNbdDJx I see the elements in array1,array2, array3 are stored as strings, I'm guessing that's the problem. But in the SQL table, the elements are of type int – Abhijith Bagepalli Apr 13 '17 at 09:54
  • I found a solution [here](http://stackoverflow.com/questions/1390983/php-json-encode-encoding-numbers-as-strings). It works fine now. I don't have enough reputation to upvote your answer but thank you very much!! – Abhijith Bagepalli Apr 13 '17 at 10:53
  • Nice - Please see my updated answer- based on the info in your comments, it sounds like the data is stored as strings so in PHP you can cast the values to floats/ints, or use the constant JSON_NUMERIC_CHECK with json_encode()... – Sᴀᴍ Onᴇᴌᴀ Apr 13 '17 at 15:14
  • I had already updated my previous answer with pretty much similar solutions as well. But thanks anyways:) – Abhijith Bagepalli Apr 14 '17 at 05:46