3

the question I am asking is from a code-architecture point of view. I am preparing a report in php which is built with a string $message and then send via a php mail function.

For example the report is built in the php file like that(basically concatenates strings):

$message .= <<<HTML
    </td>
</tr>
</tbody>
</table>
HTML;

Further, I would like to include a chart. However, trying the following example and sending it per mail I get no chart and an empty <div style="width:900px;min-height:500px"></div> ==$0 value.

$message.=<<<HTML
        <tr valign="top" align="center">
              <script type="text/javascript">
                google.charts.load("current", {packages:['corechart']});
                google.charts.setOnLoadCallback(drawChart);
                function drawChart() {

                  var data = google.visualization.arrayToDataTable([
                    ['Element', 'Density', { role: 'style' }],
                    ['Copper', 8.94, '#b87333', ],
                    ['Silver', 10.49, 'silver'],
                    ['Gold', 19.30, 'gold'],
                    ['Platinum', 21.45, 'color: #e5e4e2' ]
                  ]);

                  var options = {
                    title: "Density of Precious Metals, in g/cm^3",
                    bar: {groupWidth: '95%'},
                    legend: 'none',
                  };

                  var chart_div = document.getElementById('chart_div');
                  var chart = new google.visualization.ColumnChart(chart_div);

                  // Wait for the chart to finish drawing before calling the getImageURI() method.
                  google.visualization.events.addListener(chart, 'ready', function () {
                    chart_div.innerHTML = '<img src="' + chart.getImageURI() + '">';
                    console.log(chart_div.innerHTML);
                  });

                  chart.draw(data, options);

              }
              </script>
              <div id='chart_div'></div>
        </tr>
HTML;

My guess is that javascript is not accepted by f.ex. GMail. Hence, I am trying to create a png beforehand which is then included in the report.

My preferred way of doing this would be the google charts library, however, it has no support for php and is entirely based on JavaScript.

Hence, my questions are:

  1. How can I use the google chart library in my code?
  2. Any other suggestions if above does not work?

I appreciate if you could provide an example!

Thx in advance!

Carol.Kar
  • 4,581
  • 36
  • 131
  • 264
  • You can use a something like http://wkhtmltopdf.org/ to capture a screenshot as a png. – Steve Jul 25 '16 at 21:22
  • Have a look at this https://developers.google.com/chart/interactive/docs/printing – rjdown Jul 25 '16 at 21:25
  • @rjdown Thx for your answer! Any suggestions how to execute the javascript within php? – Carol.Kar Jul 26 '16 at 04:37
  • 1
    i would recommend having a page that draws the chart, then when the `'ready'` event fires, sends the image string (`getImageURI`) via ajax to another php, which then sends the email... – WhiteHat Jul 26 '16 at 12:40
  • @WhiteHat Can you provide a working example? I really appreciate your reply! – Carol.Kar Jul 26 '16 at 19:04
  • 1
    [here](http://stackoverflow.com/a/38464203/5090771) is a working example of getting the chart's image when the `'ready'` event fires -- although it appears from the question, you're good there -- [here](http://stackoverflow.com/a/5004276/5090771) is an excellent example of using jquery / ajax to post data back to php, including a php snippet to receive the data -- add the `$.ajax` call, with the image string as the data, to the `'ready'` event function -- there are too many pieces to construct a complete working example, not sure of a _fiddle_ that allows post back... – WhiteHat Jul 27 '16 at 11:42

1 Answers1

5

Email clients strip Javascript, SVG, and other formats, so you can't use a chart library directly in email.

Your options include:

  • Use getImageURI to generate a PNG of your chart and send it to your server to be emailed. This is probably the best solution if you know a client will load every chart before it needs to be emailed.
  • Use a tool like wkhtmltoimage to "headlessly" render a webpage that displays your charts and save it as an image.
  • Use a chart image rendering web service like QuickChart to generate the chart image (fyi: this is an open-source project that I started).

QuickChart in particular is built on Chart.js, so you'd have to create a Chart.js chart definition as a string:

$chartConfig = "{
  type: 'bar',
  data: {
    labels: ['Copper', 'Silver', 'Gold', 'Platinum'],
    datasets: [{
      data: [8.94, 10.49, 19.30, 21.45],
      backgroundColor: ['#b87333', 'silver', 'gold', '#e5e4e2'],
    }]
  },
  options: {
    title: {
      display: true,
      text: 'Density of Precious Metals, in g/cm^3',
    },
    legend: {
      display: false    
    }
  }
}";

I've used a static string to match your example, but you can include dynamic variables like in any other PHP string.

Then encode this string into a URL:

$chartUrl = 'https://quickchart.io/chart?c=' . urlencode($chartConfig);

This URL returns a chart that looks like this: Chart.js chart rendered in PHP

Finally, add the chart to your email body as an HTML image tag:

$message .= "<img src=\"$chartUrl\"/>";
ty.
  • 10,924
  • 9
  • 52
  • 71
  • I have tried this same example.But in the mail body I am only getting a box with a red cross. Can you help? – veganbu chat Jan 24 '22 at 05:13
  • @veganbuchat Can you share your full image URL? You should make sure your chart config is URL encoded. – ty. Jan 24 '22 at 15:58
  • I was successfully implemented the code. but now I need to get mysql data instead of dummy data?what changes to be done. I made a question here. https://stackoverflow.com/questions/70842364/how-to-get-mysql-data-and-generate-charts-and-attach-in-email-body – veganbu chat Jan 25 '22 at 07:03