{"id":20892906,"url":"https://github.com/a5sys/pdfbundle","last_synced_at":"2025-05-12T22:32:11.456Z","repository":{"id":50382192,"uuid":"52283909","full_name":"A5sys/PdfBundle","owner":"A5sys","description":"Bundle to integrate phpwkhtmltopdf with Symfony 2","archived":false,"fork":false,"pushed_at":"2022-07-28T15:34:43.000Z","size":8,"stargazers_count":2,"open_issues_count":1,"forks_count":2,"subscribers_count":7,"default_branch":"master","last_synced_at":"2024-11-18T05:51:39.045Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/A5sys.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-02-22T15:38:38.000Z","updated_at":"2017-04-11T20:34:18.000Z","dependencies_parsed_at":"2022-08-21T06:50:50.146Z","dependency_job_id":null,"html_url":"https://github.com/A5sys/PdfBundle","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/A5sys%2FPdfBundle","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/A5sys%2FPdfBundle/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/A5sys%2FPdfBundle/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/A5sys%2FPdfBundle/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/A5sys","download_url":"https://codeload.github.com/A5sys/PdfBundle/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225156985,"owners_count":17429701,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-18T10:14:14.501Z","updated_at":"2024-11-18T10:14:15.017Z","avatar_url":"https://github.com/A5sys.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"PdfBundle\r\n=============\r\n#### Goal\r\nThis bundle allows generation of pdf docs by using the wrapper **phpwkhtmltopdf**, which uses himself the tool **wkhtmltopdf**.\r\n\r\nThe advantage of **wkhtmltopdf** is that it's Webkit processing html code, with JS and CSS functionnal, as if the code were ran in a browser.\r\n\r\n####Why this bundle, KnpSnappyBundle already exist ?\r\n\r\nKnpSnappyBundle does not work in all cases, particularly on Windows when generated HTML has external files (CSS, JS, images).\r\nWe hit some network access, because of the PHP proc_open function, which seems buggy.\r\n\r\nAfter a successful try with phpwkhtmltopdf, this bundle was created to integrate with Symfony 2.\r\n\r\n#### dependencies\r\nRequires **phpwkhtmltopdf** and **wkhtmltopdf**.\r\n\r\n\r\n## Installation\r\n\r\nFirst install **wkhtmltopdf** (http://wkhtmltopdf.org/downloads.html)\r\n\r\nAdd dependencies in `composer.json` :\r\n```json\r\n\"a5sys/pdf-bundle\": \"dev-master\",\r\n\"mikehaertl/phpwkhtmltopdf\": \"~2.0\"\r\n```\r\n\r\nDeclare bundle in `AppKernel.php` :\r\n\r\n```php\r\nnew A5sys\\PdfBundle\\A5sysPdfBundle(),\r\n```\r\n\r\nNote: the wrapper **phpwkhtmltopdf** is a library, not a bundle.\r\n\r\n## Configuration\r\n\r\n- Install wkhtmltopdf. Be sure not to have spaces in the path.\r\n- Configure A5sys ProjectBundle\r\n\r\nIn **config.yml**, add :\r\n\r\n```yaml\r\na5sys_pdf:\r\n    binary: \"C:/wkhtmltopdf/bin/wkhtmltopdf.exe\"\r\n    # temp_dir: \"D:/tmp\"\r\n    # encoding: \"UTF-8\"\r\n    # command_options:\r\n    #    use_exec: true\r\n    #    escape_args: false\r\n    #    proc_options:\r\n    #        bypass_shell: true\r\n    #        suppress_errors: false\r\n```\r\n\r\n- binary: mandatory\r\n- temp_dir: optional, default system temp dir (C:/windows/temp).\r\n- encoding: optional, default UTF-8\r\n- command_options: optional, by default the array is created with the default children values\r\n-- use_exec: optional, default true, does the system use exec function instead of proc_open ?\r\n-- escape_args: optional, default false, does the system escape parameters before integrating it to the command ?\r\n-- proc_options: optional, default NULL, used when use_exec = false\r\n---- bypass_shell: optional, default true, adviced when on Windows\r\n---- suppress_errors: default false. Adviced to TRUE when on Windows. Generation can be done ,even if error occired. NO GUARRANTY pdf is correctly generated.\r\n\r\n## Usage\r\n\r\nExample given in a profession service.\r\n\r\n\\$this-\u003etemplating is injected twig service.\r\n\\$this-\u003epdfService is pdf service to be injected.\r\n\r\n*utf8_decode* for header et footer. Necessary to get accents.\r\n\r\n```php\r\nuse A5sys\\PdfBundle\\Service\\PdfService;\r\n\r\nclass MyService\r\n{\r\n    /**\r\n     * @var $data array\r\n     */\r\n    public function savePdf($data)\r\n    {\r\n        // HTML of pdf\r\n        $html = $this-\u003etemplating-\u003erender('MyAppBundle:Folder:my_pdf.pdf.twig', $data);\r\n\r\n        // Header in HTML\r\n        $htmlHeader = $this-\u003etemplating-\u003erender('MyAppBundle:Folder:my_header.pdf.twig');\r\n\r\n        // Footer in HTML\r\n        $htmlFooter = $this-\u003etemplating-\u003erender('MyAppBundle:Folder:my_footer.pdf.twig');\r\n\r\n        // name and path to PDF file\r\n        $fileName = uniqid() . \".pdf\";\r\n        $filePath = $this-\u003econstants['my_pdf_path'] . \"/\" . $fileName;\r\n\r\n        // note : throws ServiceException\r\n        // Generation and saving of the PDF\r\n\r\n        $options = array(\r\n           //'no-outline',\r\n            'orientation' =\u003e 'Landscape',\r\n            'header-html' =\u003e utf8_decode($htmlHeader),\r\n            'header-spacing' =\u003e '2', // space between header and content in mm\r\n            'footer-html' =\u003e utf8_decode($htmlFooter),\r\n        );\r\n\r\n        $this-\u003epdfService-\u003esaveAs(\r\n            $filePath,\r\n            $html,\r\n            $options\r\n        );\r\n    }\r\n}\r\n```\r\n\r\nTo the 2015-02-10, only saveAs is implemented for the wrapper phpwkhtmltopdf.\r\n\r\n## Options\r\n\r\nVariable **\\$options ** allows to specify options to use for the generation.\r\nAt the begining, informations from configuration will b integrated to this array. If you want to override the value of the conf, simply add the key of the wrapper **phpwkhtmltopdf** to the array.\r\n\r\nSpecific **phpwkhtmltopdf** wrapper are here:\r\nhttps://github.com/mikehaertl/phpwkhtmltopdf#special-global-options\r\n\r\nStill in **\\$options**, at the same level than specific wrapper options, you can add all options you want to give to **wkhtmltopdf**, as for example orientation , header-spacing, header-html or footer-html like shown in the example.\r\n\r\nAll wkhtmltopdf options here :\r\nhttp://wkhtmltopdf.org/usage/wkhtmltopdf.txt\r\n\r\n## Page break\r\nIn the example, \\$html varaible contains all HTML to render in PDF. It is possible to tell explicitly where to page break, simply using CSS:\r\n\r\n`\u003cdiv style=\"page-break-after: always;\"\u003e\u003c/div\u003e`\r\n\r\n## Page numbers\r\n\r\nIn the footer-html of the example, no param is given, but wkhtmltopdf do it for us ! We can get the current page number and even more, for example with this code :\r\n\r\n```html\r\n\u003c!DOCTYPE html\u003e\r\n\u003chtml\u003e\r\n    \u003chead\u003e\r\n        \u003cscript\u003e\r\n        function subst() {\r\n          var vars={};\r\n          var x=document.location.search.substring(1).split('\u0026');\r\n          for (var i in x) {var z=x[i].split('=',2);vars[z[0]] = unescape(z[1]);}\r\n          var x=['frompage','topage','page','webpage','section','subsection','subsubsection'];\r\n          for (var i in x) {\r\n            var y = document.getElementsByClassName(x[i]);\r\n            for (var j=0; j\u003cy.length; ++j) y[j].textContent = vars[x[i]];\r\n          }\r\n        }\r\n        \u003c/script\u003e\r\n    \u003c/head\u003e\r\n    \u003cbody style=\"border:0; margin: 0;\" onload=\"subst()\"\u003e\r\n        \u003ctable style=\"width: 100%\"\u003e\r\n          \u003ctr\u003e\r\n            \u003ctd style=\"text-align: left\"\u003e{{ 'now'|date('d/m/Y') }}\u003c/td\u003e\r\n            \u003ctd style=\"text-align: center\"\u003e{{ 'pdf.archival.title'|trans|raw('html') }}\u003c/td\u003e\r\n            \u003ctd style=\"text-align: right\"\u003e\r\n              {{ 'page'|trans }} \u003cspan class=\"page\"\u003e\u003c/span\u003e {{ 'pageOn'|trans }} \u003cspan class=\"topage\"\u003e\u003c/span\u003e\r\n            \u003c/td\u003e\r\n          \u003c/tr\u003e\r\n        \u003c/table\u003e\r\n    \u003c/body\u003e\r\n\u003c/html\u003e\r\n```\r\n\r\nJS works ? Yes it's Webkit that process the page, even for header-html and footer-html\r\n\r\n**Note** : Don't forget the doctype in footer and header, it won't work otherwise !\r\n\r\nThis HTML code displays the date to the left, a translated text in the center, and the text \"page x sur y\" to the right","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fa5sys%2Fpdfbundle","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fa5sys%2Fpdfbundle","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fa5sys%2Fpdfbundle/lists"}