• статья
  • pantey

Сохраняем значения кастомной формы в PDF файл

12.10.2015

Итак, сегодня займемся совершенно не тривиальной задачей, а именно той, которая все чаще попадается мне на проектах, а именно сохранение значений формы в PDF документ. Данная технология, в основном используется в интернет магазинах, да и в других сервисах, где требуется выставление счетов или снять какие-то показатели сайта.

Как всегда, все делаем на примере. У меня есть базовая форма, которая состоит из 3х полей:

  • Ваше имя
  • Ваш пол
  • Текст сообщения
Простейшая форма Drupal 7

Я опускаю, как создавать простейшие формы, ибо все это уже проходили.

Ну или код модуля, файл custom_form.module:
  1. <?php
  2.  
  3. /**
  4.  * Implements hook_menu()
  5.  */
  6. function custom_form_menu(){
  7.  
  8. $items['custom-form'] = array(
  9. 'title' => 'My custom form',
  10. 'page callback' => 'drupal_get_form',
  11. 'page arguments' => array('custom_form_form'),
  12. 'access callback' => TRUE,
  13. );
  14.  
  15. return $items;
  16.  
  17. }
  18.  
  19. /**
  20.  * Implements hook_form()
  21.  */
  22. function custom_form_form($form, &$form_state){
  23.  
  24. // Text field
  25. $form['name'] = array(
  26. '#title' => 'Your name',
  27. '#type' => 'textfield',
  28. '#required' => TRUE,
  29. );
  30.  
  31. // Select
  32. $form['sex'] = array(
  33. '#title' => 'Your sex',
  34. '#type' => 'select',
  35. '#options' => drupal_map_assoc(array('man', 'woomen')),
  36. '#empty_option' => 'Select your sex',
  37. '#required' => TRUE,
  38. );
  39.  
  40. // Textarea
  41. $form['message'] = array(
  42. '#title' => 'Your message',
  43. '#type' => 'textarea',
  44. '#required' => TRUE,
  45. );
  46.  
  47. // Submit
  48. $form['submit'] = array(
  49. '#value' => 'Save value to PDF',
  50. '#type' => 'submit',
  51. );
  52.  
  53. return $form;
  54.  
  55. }
  56.  
  57. /**
  58.  * Implements hook_form_submit
  59.  */
  60. function custom_form_form_submit($form, &$form_state){
  61.  
  62. $result = $form_state['values'];
  63.  
  64. }

По сабмиту, у нас естественно ничего не происходит. Теперь к самому интересному, как создать PDF документ. PHP из коробки не умеет работать с PDF документами, только с подключением дополнительных библиотек. Библиотек очень большое количество, а действительно адекватно работающих не так уж и много. Я перепробовал их огромное количество и для себя выбрал 2:

В нашем случае, я буду использовать первый вариант TCPDF. Первое, что нужно сделать – это скачать саму библиотеку и распаковать ее в корень своего модуля.

Теперь в сабмите подключим данную библиотеку

  1. <?php
  2. module_load_include('php', 'custom_form', 'tcpdf/tcpdf');

Ну а дальше, нам остается лишь задать параметры PDF документа и определить, что делать с данным файлом после создания. Я, данный документ буду сохранять в БД и отправлять его пользователю на скачивание. Список примеров и параметров данной библиотеки можно посмотреть здесь

Ну а дальше по коду и комментариям должно быть все понятно

Хочу заметить, что данный файл в БД, будет сохраняться в течении нескольких часов, ибо статус у него 0, если же вам нужно сохранить его навсегда, то меняем на 1.

Файл модуля custom_form.module
  1. <?php
  2.  
  3. /**
  4.  * Implements hook_menu()
  5.  */
  6. function custom_form_menu(){
  7.  
  8. $items['custom-form'] = array(
  9. 'title' => 'My custom form',
  10. 'page callback' => 'drupal_get_form',
  11. 'page arguments' => array('custom_form_form'),
  12. 'access callback' => TRUE,
  13. );
  14.  
  15. return $items;
  16.  
  17. }
  18.  
  19. /**
  20.  * Implements hook_form()
  21.  */
  22. function custom_form_form($form, &$form_state){
  23.  
  24. // Text field
  25. $form['name'] = array(
  26. '#title' => 'Ваше имя',
  27. '#type' => 'textfield',
  28. '#required' => TRUE,
  29. );
  30.  
  31. // Select
  32. $form['sex'] = array(
  33. '#title' => 'Ваш пол',
  34. '#type' => 'select',
  35. '#options' => drupal_map_assoc(array('мужской', 'женский')),
  36. '#empty_option' => 'Select your sex',
  37. '#required' => TRUE,
  38. );
  39.  
  40. // Textarea
  41. $form['message'] = array(
  42. '#title' => 'Сообщение',
  43. '#type' => 'textarea',
  44. '#required' => TRUE,
  45. );
  46.  
  47. // Submit
  48. $form['submit'] = array(
  49. '#value' => 'Save value to PDF',
  50. '#type' => 'submit',
  51. );
  52.  
  53. return $form;
  54.  
  55. }
  56.  
  57. /**
  58.  * Implements hook_form_submit
  59.  */
  60. function custom_form_form_submit($form, &$form_state){
  61.  
  62. module_load_include('php', 'custom_form', 'tcpdf/tcpdf'); // Подключаем библиотеку TCPDF
  63.  
  64. $name_file = 'result-' .time() .'.pdf'; // Создали уникальное имя файла
  65. $result = $form_state['values']; // Массив срезультатами формы
  66. $html ='<h1>Результаты заполнения формы</h1>
  67. <ul>
  68. <li>Ваше имя: ' .$result['name'] .'</li>
  69. <li>Ваше пол: ' .$result['sex'] .'</li>
  70. <li>Сообщение: ' .$result['message'] .'</li>
  71. </ul>';
  72.  
  73. $pdf = new TCPDF('P', 'mm', 'A4', true, 'UTF-8', false); // создаем объект TCPDF
  74. $pdf->SetMargins(20, 25, 25); // отступы страницы
  75. $pdf->SetFont('dejavusans', '', 16); // используемый шрифт и его размер
  76. $pdf->AddPage(); // создали страницу
  77.  
  78. $pdf->Writehtml($html, true, false, true, false, '');
  79.  
  80. $url_to_path = 'public://' .$name_file;
  81. $pdf->Output($url_to_path, 'F'); // сохраняем файл на сервере
  82.  
  83. // Сохраняем файл в БД
  84. if(user_is_anonymous()){
  85. $uid = '';
  86. }else{
  87. global $user;
  88. $uid = $user->uid;
  89. }
  90.  
  91. $uri = $url_to_path;
  92.  
  93. // Создаем объект файла
  94. $file = new stdClass;
  95. $file->uid = $uid;
  96. $file->filename = $name_file;
  97. $file->uri = $uri;
  98. $file->filemime = 'application/pdf';
  99. $file->filesize = filesize($uri);
  100. $file->status = 0;
  101.  
  102. file_save($file);
  103.  
  104. // Отдаем файл на скачивание конечному пользователю
  105. file_transfer($url_to_path, array(
  106. 'Content-Type' => 'application/octet-stream',
  107. 'Content-Disposition' => 'attachment; filename="' .$url_to_path . '"',
  108. 'Content-Length' => filesize($url_to_path)
  109. )
  110. );
  111.  
  112. }

Сам готовый модуль, используемый в примере можно скачать здесь. По всем остальным вопросам - как всегда в комментариях.

Хочу заметить, что вместе с модулем идет и библиотека TCPDF, отсюда и вес в 17mb.

-->
Узнавай о новых статьях сайта - первым. Просто подпишись на рассылку.

Комментарии (4)

Profile picture for user 1541
Руслан
23.10.2015

Где это применять? Зачем такое нужно может быть?

Profile picture for user pantey
pantey
23.10.2015

например для выставления счета оплаты в банке.

Profile picture for user 1541
Станислав
13.03.2016

Штука крутая, а как такое реализовать для разных шаблонов. Чтоб можно было их выбрать. Я имею в виду конечный пдф, чтоб имер разный вид в нутри к примеру для одной компании с одной шапкой и тремя столбиками, а дя другой с двумя столбиками и своей шапкой. И в нагрузгу не только пдф но и эксэль )

Profile picture for user pantey
pantey
14.03.2016

добавляете дополнительный радиобаттон в форму и при сабмите проверяете занчение радиобаттона и на основе этого генерируете PDF. Для exel попробуйте использовать библиотеку php exel