-
-
Save webdevilopers/e0d34a1c04ef2050a450 to your computer and use it in GitHub Desktop.
<?php | |
namespace Plusquam\Bundle\ContractBundle\Controller; | |
use Symfony\Bundle\FrameworkBundle\Controller\Controller; | |
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method; | |
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; | |
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template; | |
use Symfony\Component\HttpFoundation\Response; | |
use Symfony\Component\HttpFoundation\Request; | |
use Ob\HighchartsBundle\Highcharts\Highchart; | |
/** | |
* Bundle controller. | |
* | |
*/ | |
class BundleController extends Controller | |
{ | |
/** | |
* @Route("/qis/contract/{contractId}/bundle/list") | |
* @Template() | |
*/ | |
public function listAction(Request $request) | |
{ | |
$contractId = $request->get('contractId'); | |
// Chart | |
$series = array( | |
array("name" => "Data Serie Name", | |
"data" => array(1,2,4,5,6,3,8), | |
// @see http://blog.psyrendust.com/2012/12/03/wkhtmltopdf-setup-guide-with-knplabs-snappy-support-on-debian/ | |
'animation' => false // important? | |
) | |
); | |
$ob = new Highchart(); // uses zend components? json, stdlib | |
$ob->chart->renderTo('linechart'); // The #id of the div where to render the chart | |
$ob->title->text('Chart Title'); | |
$ob->xAxis->title(array('text' => "Horizontal axis title")); | |
$ob->yAxis->title(array('text' => "Vertical axis title")); | |
$ob->series($series); | |
$ob->plotOptions->pie(array( | |
'animation' => false, | |
'enableMouseTracking' => false, | |
'shadow' => false | |
)); | |
$em = $this->getDoctrine()->getManager(); | |
$parttypes = $em->getRepository('Plusquam\Bundle\ContractBundle\Entity\Bundle') | |
->getGroupedParttypes(array('contract' => $contractId), true, false); | |
$parttypesGroupedByShippingNumber = $em->getRepository('Plusquam\Bundle\ContractBundle\Entity\Bundle') | |
->getGroupedParttypes(array('contract' => $contractId), true, true); | |
$viewParameters = array( | |
'contract' => $contract, | |
'parttypes' => $parttypes, | |
'parttypesGrouped' => $parttypesGrouped, | |
'parttypesGroupedByShippingNumber' => $parttypesGroupedByShippingNumber, | |
'chart' => $ob | |
); | |
if ($request->get('pdf')) { | |
$html = $this->renderView('PlusquamContractBundle:Bundle:list.html.twig', $viewParameters); | |
$snappy = $this->get('knp_snappy.pdf'); | |
return new Response( | |
$snappy->getOutputFromHtml($html, array( | |
'orientation' => 'Landscape', | |
'images' => true, | |
'enable-javascript' => true | |
)), | |
200, | |
array( | |
'Content-Type' => 'application/pdf', | |
'Content-Disposition' => 'attachment; filename="report.pdf"' | |
) | |
); | |
} | |
return $viewParameters; | |
} | |
} |
framework: | |
templating: | |
assets_base_urls: http://localhost:8001 # run on a different port using another single-threaded built-in webserver |
<img src="{{ asset('logo.png', absolute=true) }}"> | |
<div id="linechart" style="min-width: 400px; height: 400px; margin: 0 auto"></div> | |
<script src="{{ asset('/bundles/sonatacore/vendor/jquery/dist/jquery.min.js') }}" type="text/javascript"></script> | |
<script src="{{ asset('/highcharts/highcharts.js') }}" type="text/javascript"></script> | |
<script type="text/javascript"> | |
{{ chart(chart) }} | |
</script> | |
@webdevilopers I don't have experience with twig, but you could try to rearrange your scripts so that it's below your div#linechart
.
<div id="linechart" style="min-width: 400px; height: 400px; margin: 0 auto"></div>
<script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
<script src="http://code.highcharts.com/highcharts.js"></script>
<script src="http://code.highcharts.com/modules/exporting.js"></script>
<script type="text/javascript">
(function($){
$(function() {
var linechart = new Highcharts.Chart({
chart: {"renderTo":"linechart"},
plotOptions: {"pie":{"animation":false,"enableMouseTracking":false,"shadow":false,"images":true,"enable-javascript":true,"javascript-delay":500}},
series: [{"name":"Data Serie Name","data":[1,2,4,5,6,3,8],"animation":false}],
title: {"text":"Chart Title"},
xAxis: {"title":{"text":"Horizontal axis title"}},
yAxis: {"title":{"text":"Vertical axis title"}}
});
});
})(jQuery);
</script>
Also with snappy I was setting the javascript-delay
to 500
milliseconds. This was to ensure that snappy has enough time to render the page before printing it out to echo
.
$snappy->setOption('javascript-delay', 500);
I would check to see if your page is even rendering the chart without the print to pdf part. If it is, then your delay might not be long enough.
Thanks @psyrendust. I think I found the major problem by checking if javascript is correctely executed:
<script src="/bundles/sonatacore/vendor/jquery/dist/jquery.min.js" type="text/javascript"></script>
<script src="/highcharts/highcharts.js"></script>
<script type="text/javascript">
document.write('X');
$( document ).ready(function() {
document.write('JQ');
});
{{ chart(chart) }}
</script>
While my regular page will load the jQuery part and output "JQ" my PDF only shows "X".
Javascript is executed but not jQuery. I guess it is a problem with the assets path.
I will check that!
I replaced the path with the official twig assets:
<script src="{{ asset('/bundles/sonatacore/vendor/jquery/dist/jquery.min.js') }}" type="text/javascript"></script>
But still no success. Then I included the CDN version:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
Which includes jQuery but the chart is still not generated.
So I will have to check the path problem in twig and why Highcharts still won't work even with different delays.
Regarding the javascript delay I misunderstood you @psyrendust ! I now set it on snappy
directely:
$snappy = $this->get('knp_snappy.pdf');
$snappy->setOption('javascript-delay', 500);
Now I get this error:
The exit status code '1' says something went wrong:
stderr: "Unknown long argument --javascript-delay
Well there is an array of options you can pass instead e.g.:
return new Response(
$snappy->getOutputFromHtml($html, array(
'lowquality' => false,
'encoding' => 'utf-8',
'images' => true,
'enable-javascript' => true,
'javascript-delay' => 5000
)),
200,
array(
'Content-Type' => 'application/pdf',
'Content-Disposition' => 'attachment; filename="report.pdf"'
)
);
But this time:
The exit status code '1' says something went wrong:
stderr: "Unknown long argument --images
The mentioned errors really seem to be wkhtmltopdf 0.9.9
related issues. I've updated to 0.12 (with patched qt) and will try again.
BTW I tried generating a PDF from an URL with charts - I don't know if Javascript is executed for this purpose. But there is a chart - though it looks terrible. :)
$this->get('knp_snappy.pdf')->generate('http://www.highcharts.com/stock/demo/', '/home/foo/snappy.pdf');
It looks like this is a Highchart
issue. I easily created an example using jqPlot
.
Following this issue related to Highchart
:
wkhtmltopdf/wkhtmltopdf#1964
There seems to be an issue with wkhtmltopdf
and HighCharts
using specific ports like 8000 or 8080:
Still checking. Any help would be appreciated!
@barryvdh @docteurklein @MarieMinasyan @skybondsor @colejarczyk
Indeed there is a port problem but NOT WITH wkhtmltopdf
.
My symfony2
app runs on the PHP built-in webserver. This webserver is single-threaded
only.
Multiple processes like generating the PDF on the hand while loading assets
like images
or javascript
on the other hand will result in a timeout when using Snappy
.
PHP applications will stall if a request is blocked.
http://stackoverflow.com/questions/25062398/max-concurrent-connections-for-phps-built-in-development-server
The embedded web server is for testing purpose and not meant as a full web server. This limitation along with others (like missing vhost support etc.) is by design and we don't have any plans to change that as there are multiple good web servers already which work nicely with PHP.
https://bugs.php.net/bug.php?id=67884
I havn't tested my code on a production server yet but it should work out of the box.
In order to make it working on your local machine when using the built-in server and Symfony2
you can route the assets
to a different URL / port:
# app/config/config_dev.yml
framework:
templating:
assets_base_urls: http://localhost:8001
as suggested by @docteurklein in issue KnpLabs/snappy#58 (comment).
Now the HighCharts
will show up using the code provided in this gist.
Of course you will have to run a second instance of the built-in webserver on the new port 8001:
Ps.: Paths to assets e.g. images
maybe need to be absolute:
<img src="{{ asset('logo.png', absolute=true) }}">
I've tried all said here without success... The last and stupid shot worked, still don't know why. I'm running my symfony2 app under apache server in my machine. I'm using Ubuntu 14.10
with wkhtmltopdf 0.12.2.1
I've created two routes: one to render the html
with the chart and other to create the pdf
with the generated absolute url from first route.
Testing with the command line all works fine:
wkhtmltopdf --javascript-delay 10000 http://www.highcharts.com/demo/line-basic test.pdf
The test code:
public function indexAction()
{
$series = array(
array("name" => "Data Serie Name", "data" => array(1, 2, 4, 5, 6, 3, 8))
);
$ob = new Highchart();
$ob->chart->renderTo('linechart'); // The #id of the div where to render the chart
$ob->title->text('Chart Title');
$ob->xAxis->title(array('text' => "Horizontal axis title"));
$ob->yAxis->title(array('text' => "Vertical axis title"));
$ob->series($series);
$ob->plotOptions->series(array(
'animation' => false,
'enableMouseTracking' => false,
'shadow' => false
));
return $this->render('LogBundle:Reports:teste.html.twig', array(
'chart' => $ob
));
}
public function testAction() {
$url = $this->generateUrl('test_index_route', array(), UrlGeneratorInterface::ABSOLUTE_URL);
return $this->container->get('knp_snappy.pdf')->generate($url, '/home/cassiano/Desktop/file.pdf');
}
Found the issue, in my template: LogBundle:Reports:teste.html.twig
I was adding the highcharts.js
without the url scheme, like this:
<script src="//code.highcharts.com/4.0.1/highcharts.js"></script>
After adding http:
to url the chart appeared in the pdf.
Now I understood why just calling asset
in twig
with dev env leaving default value in assets_base_urls
rendered blank chart. Maybe if add assets_base_urls
the same vhost
name it will rendered too instead of using:
{{ app.request.scheme ~'://' ~ app.request.httpHost ~ asset(...) }}
I access my symfony app by http://myapp/app_dev.php/...
Possible related question by @dev_julien:
http://stackoverflow.com/questions/29951995/display-query-datas-on-highchart-js-graphics-from-doctrine-queries-in-symfony
Thank!!!
Blog by @psyrendust:
and by @claytonlz:
recommend setting all animations to false.
In order for wkhtmltopdf to correctly print the chart, it is advised to remove any animations on hicharts.js objects. You will need to set the {javascript}animation{/javascript} property to false for both the {javascript}Chart{/javascript} object and the {javascript}plotOptions.series{/javascript} object.
It looks like the Highcharts API has changed and you cannot disable animation on the chart object directely. It must now be done on the
plotOptions
for a single type or all types resp.series
:http://stackoverflow.com/questions/13831501/highcharts-turn-animation-false-for-line-chart
Still the chart won't show up.