понеділок, 9 липня 2012 р.

PDFLib для PHP

Розглянемо процес генерування PDF документів засобами PHP. Для цього існує ряд бібліотек, одною з таких є PDFLib. Розглянемо основні особливості роботи з даною бібліотекою. Усі приклади перевірені на PHP 5.2.4. При роботі з PHP 5.3 можливо прийдеться внести певні зміни.

1. Встановлення і налаштування необхідних елементів
Для роботи необхідно поставити пакет веб-розробника денвер. Що можна завантажити з офіційного сайту або самостійно поставити веб-сервер Apache та php. Процес встановлення можна почитати в офіційній документації.

Для встановлення бібліотеки, що дозволить нам генерувати pdf документи необхідно:

• Зайти на http://php.net/releases/ і скачати колекцію PECL модулів для відповідної версії інтерпритатора PHP, яка встановлена у Денвері 3. У випадку встановлення Денвера 3 з офіційного сайту з php 5.2.4, качаємо наступний архів zip: http://museum.php.net/php5/pecl-5.2.4-Win32.zip. При використанні безплатного модуля з оф. сайту pdflib у створеному документі буде непотрібний нам фоновий напис, тому то користуємося PECL модулем.

• З даного архіву беремо php_pdf.dll і кладемо її в директорію:
     <denwer_root>\usr\local\php5\ext\ 
• В <denwer_root>\usr\local\php5\php.ini знаходимо секцію Windows Extensions і додаємо наступний рядок тексту:   
     extension=php_pdf.dll
• Перезапускаємо Apache — на цьому встановлення завершене.
• Для перевірки можна скористатися функцією phpinfo(). У виданій нею інформації повинно бути вказана підтримка pdf, що й зображено на рисунку.Для цього необхідно створити файл з розширення php із наступним змістом:
         
    <?
      PHP  
      phpinfo(); 
    ?>

Далі при запущеному Apache запустити його на виконання ввівши URL-адресу у веб-браузері.

Бібліотеку pdf підключено


2. Друк тексту

Після того як усе встановлено починаємо створення документу. Наступна програма демонструє створення pdf документу з однією сторінкою і написом на даній сторінці.
  
         <?php
          // Створити вказівник на новий PDF документ
          $pdf = pdf_new();
          // відкрити файл (міняємо адресу під власну)
          pdf_open_file($pdf, "/home/univer.ua/www/example1.pdf"); 
          // розпочати нову сторінку (A4)
          pdf_begin_page($pdf, 595, 842);
          // отримати і використати об'єкт шрифт з кириличною кодировкою cp1251
          $fontdir = "C:\WINDOWS\Fonts";
          pdf_set_parameter($pdf, "FontOutline", "arialMyName=$fontdir\arial.ttf");
          $arial = pdf_findfont($pdf,"arialMyName", "cp1251" ,0 );
          pdf_setfont($pdf, $arial, 10);
          // надрукувати текст
          pdf_show_xy($pdf, "Це перший рядок нашого документу,", 50, 750); 
          pdf_show_xy($pdf, "а це другий рядок", 50,730);
          // кінець сторінки
          pdf_end_page($pdf);
          // закрити і зберегти файл
          pdf_close($pdf);
        ?>

Після збереження скрипта під певною назвою (наприклад test.php), його можна запустити у браузері за адресом ВІРТУАЛЬНИЙ_ХОСТ/test.php. Так якщо був створений віртуальний хост univer.ua, то відповідно адреса буде http://univer.ua/test.php. За адресою вказаною на початку файлу буде створений example1.pdf. Результат зображено на рисунку:
Простий PDF документ
Почнемо з першого кроку – створення вказівника на PDF файл.
  
    $pdf = pdf_new();
Це здійснюється за допомогою функції pdf_new(), яка повертає вказівник на цей документ. Згодом цей вказівник використовується для всіх наступних інструкцій по створенню PDF документу.
 
       // відкриваємо файл
       pdf_open_file($pdf, "example.pdf");
Як тільки документ був створений, в нього можна вставити початок нової сторінки функцією pdf_begin_page()
 
      // розпочати нову сторінку (A4)
      pdf_begin_page($pdf, 595, 842); 
І кінець сторінки функцією pdf_end_page().
      // end page
      pdf_end_page($pdf);  
Якщо ще потрібні сторінки, то знову ж потрібно використати ці функції. Функція pdf_begin_page() потребує два додаткові параметри - ширину і висоту створюваного документу в пунктах (один пункт(точка) рівний 1/72 дюйма). Між викликом pdf_begin_page() і pdf_end_page() знаходиться код, який пише в файл. Це може бути вставка тексту, картинок або геометричних фігур. В даному випадку – це лише текст. Тому все що необхідно вибрати шрифт і використати його в тексті документу. Вибір і регістрація шрифтів виконується функцією pdf_findfont() та pdf_setfont().

Функція pdf_findfont() вибирає шрифт для використання в документі, і вимагає ввести ім’я шрифту, метод кодування та булевий параметр, що вказує чи слід його інтегрувати в PDF документ; а повертає вона об’єкт-шрифт, який можна згодом використовувати при виклику функції pdf_setfont(). Виклик даної функції необхідно буде здійснювати на кожній сторінці документу, навіть якщо шрифт той же що і на попередніх.
        // отримати і використати об'єкт шрифт
        $fontdir = "C:\WINDOWS\Fonts";
        pdf_set_parameter($pdf, "FontOutline", "arialMyName=$fontdir\arial.ttf");
        $arial = pdf_findfont($pdf,"arialMyName", "cp1251" ,0 );
        pdf_setfont($pdf, $arial, 10);  
Як тільки шрифт вибраний, можна використати функцію pdf_show_xy() для запису тексту у відповідне місце на сторінці.
      // надрукувати текст
      pdf_show_xy($pdf, "Це перший рядок нашого документу,",50,750); 
      pdf_show_xy($pdf, "а це другий рядок", 50,730);
Функція вимагає вказівник на PDF документ, посилання на об’єкт-шрифт, текст для запису і координати X Y, куди починати записувати текст. Ці координати вказуються відносно точки (0,0), яка знаходиться в лівому нижньому куті документу, а не у верхньому як можна б було сподіватись.
Як тільки текст був записаний, сторінка закривається викликом функції pdf_end_page(). Далі можна додати ще сторінку або, просто закрити документ із допомогою pdf_close(). Дана функція зберігає документ з ім’ям вказаним при виклику pdf_open_file() і знищує вказівник на документ.

3. Вставлення зображень

Розширення PDF в PHP дозволяє набагато більше, ніж просто писати текст в документ. Так можна додавати зображення у документ. Далі наводиться приклад, який здійснює це.
  
      <?php
        // створити вказівник для нового PDF документу
        $pdf = pdf_new();
        
        // відкрити файл
        pdf_open_file($pdf, "/home/univer.ua/www/example1.pdf"); 
        
        // розпочати нову сторінку (A4)
        pdf_begin_page($pdf, 595, 842);
        
        // отримати і використати об'єкт шрифт
        $fontdir = "C:\WINDOWS\Fonts";
        pdf_set_parameter($pdf, "FontOutline", "arialMyName=$fontdir\arial.ttf");
        $arial = pdf_findfont($pdf,"arialMyName", "cp1251" ,0 );
        pdf_setfont($pdf, $arial, 10);
        
        // надрукувати текст
        pdf_show_xy($pdf, "Еней був паробок моторний,",60, 750); 
        pdf_show_xy($pdf, "і хоть куди козак", 60, 730);
        pdf_show_xy($pdf, "Удавсь на всеє зле проворний,", 60, 710);
        pdf_show_xy($pdf, "Завзятіший од всіх бурлак", 60, 690);
        
        // додати зображення над текстом і після
        $image = pdf_open_image_file($pdf, "jpeg", "/home/univer.ua/www/univer.jpg", 0, 0);
        pdf_place_image($pdf, $image, 70, 770, 0.25);
        pdf_place_image($pdf, $image, 70, 660, 0.25);
        // кінець сторінки
        pdf_end_page($pdf);
        
        // закрити і зберегти файл
        pdf_close($pdf);
      ?>
Вставлення зображень в pdf
Вставка зображення здійснюється за допомогою двох функцій pdf_open_image_file() та pdf_place_image(). Перша з них приймає тип зображення - GIF, JPEG, TIFF або PNG – та назву файлу в якості аргументів, і повертає вказівник на зображення, який згодом можна повторно використовувати в документі.

Вказівник на рисунок, повернутий вище, далі можна передати функції pdf_place_image(), яка розташує зображення у певному місці на сторінці. Координати, передані даній функції (другий і третій аргумент) відносяться до лівого нижнього кута зображення, а четвертий аргумент задає параметр масштабування рисунку при відображенні (1 – покаже зображення у 100% масштабі, 0.5 – зменшить його в два рази.)

 4. Малювання ліній

Модуль PDF включає в себе велику кількість функцій, які можуть малювати ліній, круги та інші фігури. Ось код, що здійснює малювання лінії:
  
      <?php
        // створити вказівник для PDF документу
        $pdf = pdf_new();
        
        // відкрити файл
        pdf_open_file($pdf, "/home/univer.ua/www/letter.pdf");
        
        // розпочати сторінку (A4)
        pdf_begin_page($pdf, 595, 842);
        
        // отримати і використати об'єкт шрифт
        $fontdir = "C:\WINDOWS\Fonts";
        pdf_set_parameter($pdf, "FontOutline", "arialMyName=$fontdir\arial.ttf");
       $arial = pdf_findfont($pdf,"arialMyName","cp1251",0);
        pdf_setfont($pdf, $arial, 15);
        
        // встановити колір для ліній
        pdf_setcolor($pdf, "stroke", "rgb", 0, 0, 0, 0);
        
        // встановити логотип з самого верху сторінки по центру
        $image = pdf_open_image_file($pdf, "jpeg", "/home/univer.ua/www/univer.jpg", 0, 0);
        pdf_place_image($pdf, $image, 170, 785, 0.5);
        
        // намалювати лінію під логотипом
        pdf_moveto($pdf, 20, 780);
        pdf_lineto($pdf, 575, 780);
        pdf_stroke($pdf);
        
        // намалювати лінію знизу сторінки
        pdf_moveto($pdf, 20,50); 
        pdf_lineto($pdf, 575, 50); 
        pdf_stroke($pdf);
        
        // написати деякий текст під лінією
        pdf_show_xy($pdf, "Цілком конфіденційно", 200, 35);
        
        // кінець сторінки
        pdf_end_page($pdf);
        
        // close and save file
        pdf_close($pdf);
      ?>
В результаті letter.pdf матиме вигляд:
Лінії в pdf
В даному випадку малювання лінії включає в себе використання функцій pdf_moveto(), pdf_lineto() та pdf_stroke().
В наведеному вище прикладі малюється лінія з точки (20,780) до точки (575, 780). Щоб це зробити, спочатку необхідно помістити курсор в початкову точку (20,780), з допомогою функції pdf_moveto().
  pdf_moveto($pdf, 20, 780);
Далі необхідно задати кінцеву точку з допомогою pdf_lineto():
  pdf_lineto($pdf, 575, 780);
Далі малюється лінія з допомогою pdf_stroke().
  pdf_stroke($pdf); 
Колір лінії задається функцією pdf_setcolor(), яка приймає декілька параметрів: вказівник на PDF документ, тип лінії: "stroke", "fill" або "both", кольорова палітра (RGB або CMYK), і список кольорових значень, що підходять до вибраної палітри.
pdf_setcolor($pdf, "stroke", "rgb", 0, 0, 0, 0);
Необхідно помітити, що список кольорових значень, що передаються pdf_setcolor() повинен бути заданий в процентій величині інтенсивності - тобто, інтенсивність даного кольору, виражена в процентах від максимально можливого. Наприклад, якщо я хочу задати (RGB: 255,0,0) в якості кольору, виклик функції pdf_setcolor() буде виглядати так:
  pdf_setcolor($pdf, "stroke", "rgb", 1, 0, 0, 0);
 Заливка жовтим кольором буде виглядати так:
  pdf_setcolor($pdf, "fill", "rgb", 1, 1, 0, 0);
 
5. Квадрати та круги 

Лінії - це не єдине, що можна малювати – круги і прямокутники також можна малювати.
  
      <?php
        // створити вказівник на PDF документ
        $pdf = pdf_new();
        
        // відкрити файл
        pdf_open_file($pdf, "/home/univer.ua/www/shapes.pdf");
        
        // розпочати нову сторінку (A4)
        pdf_begin_page($pdf, 595, 842);
        
        // встановити колір заповнення
        pdf_setcolor($pdf, "fill", "rgb", 1, 1, 0, 0);
        
        // встановити колір малювання контору
        pdf_setcolor($pdf, "stroke", "rgb", 0, 0, 0, 0);
        
        // намалювати прямокутник
        pdf_rect($pdf, 50, 500, 200, 300);
        pdf_fill_stroke($pdf);
        
        // встановити колір заповнення
        pdf_setcolor($pdf, "fill", "RGB", 0, 0.25, 0.5, 0);
        
        // встановити колір малювання контору
        pdf_setcolor($pdf, "stroke", "rgb", 0, 0, 1, 0);
        
        // намалюватиколо
        pdf_circle($pdf, 150, 650, 100);
        pdf_fill_stroke($pdf);
        
        // кінець сторінки
        pdf_end_page($pdf);
        
        // закрити і зберегти документ
        pdf_close($pdf);
      ?>
Коло намальоване на квадраті  

В даному випадку функція the pdf_rect() використовується для малювання прямокутника із допомогою заданих координат лівого нижнього кута, висоти і ширини. Далі прямокутник замальовується і обводиться двума різними кольорами з допомогою функції
  
       pdf_fill_stroke()
       pdf_setcolor($pdf, "fill", "rgb", 1, 1, 0, 0);
       pdf_setcolor($pdf, "stroke", "rgb", 0, 0, 0, 0);
       pdf_rect($pdf, 50, 500, 200, 300);
       pdf_fill_stroke($pdf);
Круги малюються функцією pdf_circle(), яка приймає три аргументи: координати X та Y центру кругу і довжини радіусу.
       pdf_circle($pdf, 150, 650, 100);
Можливість малювання геометричних зображень "на льоту" може пригодитися в різних ситуаціях. Наприклад, з використанням циклу "for" та функції pdf_lineto() можна згенерувати сітку з ліній.
  
      <?php
        // створити вказівник на новий PDF документ
        $pdf = pdf_new();
        
        // відкрити файл
        pdf_open_file($pdf, "/home/univer.ua/www/grid.pdf");
        
        // створити нову сторінку (A4)
        pdf_begin_page($pdf, 595, 842);
        
        // встановити колір малювання
        pdf_setcolor($pdf, "stroke", "rgb", 0, 0, 0, 0);
        
        // намалювати вертикальні лініх (рухаємось по осі X з кроком 20)
        for ($x=0; $x<=595; $x+=20)
        {
         pdf_moveto($pdf, $x, 0);
         pdf_lineto($pdf, $x, 842);
         pdf_stroke($pdf);
        }
        
        // намалювати горизонтальні лінії (рухаємося по осі Y)
        for ($y=0; $y<=842; $y+=20)
        {
         pdf_moveto($pdf, 0, $y);
         pdf_lineto($pdf, 595, $y);
         pdf_stroke($pdf);
        }
                // кінець сторінки
        pdf_end_page($pdf);
        
        // закрити і зберегти файл
        pdf_close($pdf);
      ?>

Сітка на PDF-сторінці
6. Задання інформації про документ

Можна задавати інформацію про документ із допомогою функцій сімейства pdf_set_info(); Ця інформація визначає творця документа, назву і вміст. Наступний приклад демонструє це:
  
      <?php
        // створити вказівник для нового PDF документу
        $pdf = pdf_new();
        
        // відкрити файл
        pdf_open_file($pdf, "/home/univer.ua/www/eneida.pdf");
        
        // розпочати нову сторінку (A4)
        pdf_begin_page($pdf, 595, 842);
        
        // встановити інформацію про документ
        pdf_set_info($pdf, "Author", "Іван Котляревський");
        pdf_set_info($pdf, "Creator", "Іван Котляревський");
        pdf_set_info($pdf, "Title", "Енеїда"); 
        pdf_set_info($pdf, "Subject", "Початок"); 
        pdf_set_info($pdf, "Keywords", "Еней козак Троя");
        
        // отримати і використати об'єкт шрифт
        $fontdir = "C:\WINDOWS\Fonts";
        pdf_set_parameter($pdf, "FontOutline", "arialMyName=$fontdir\\times.ttf");
        $arial = pdf_findfont($pdf,"arialMyName", "cp1251" ,0 );
        pdf_setfont($pdf, $arial, 12);
        
        // надрукувати текст
        pdf_show_xy($pdf, "Еней був паробок моторний",60, 750); 
        pdf_show_xy($pdf, "І хлопець хоть куди козак", 60, 730);
        pdf_show_xy($pdf, "Удавсь на всеє зле проворний,", 60, 710);
        pdf_show_xy($pdf, "Завзятіший од всіх бурлак", 60, 690);
        
        
        // кінець сторінки
        pdf_end_page($pdf);
        
        // закрити і зберегти документ
        pdf_close($pdf);
      ?>  
Далі при перегляді документу в Adobe Reader, ви зможете побачити цю інформацію у Властивостях документу.

Властивості документу

Як бачимо опис кожного пункту описується окремо у pdf_set_info().

7. Кругові діаграми

Наступний приклад демонструє як PHP може приймати числові дані і генерувати з них діаграми, наприклад, так звані «кругові діаграми»

Форма знизу запитує декілька порцій даних, у вигляді чисел, що розділяються комами. Після вводу декількох чисел скрипт "pie.php" конвертує їх із абсолютних чисел в сектори даних відносних розмірів і використовує дані сектори для генерації PDF документу, що містить кругову діаграму, виділяючи різні сектори і заливаючи їх різними кольорами.
  

<html>
<head>
<basefont face=arial>
</head>

<body>

<h3>Pie Chart Generator</h3>
<table cellspacing="5" cellpadding="5">
<form action="pie.php" method=POST>
<tr>
<td>Enter numeric values (pie segments), separated by commas</td> </tr>
<tr> <input name="data" type="text" /></td> </tr> <tr> <td><input name="submit" type="submit" value="Generate PDF Pie Chart" /></td> </tr>

</form> </table>

</body>
</html>


А ось скрипт:
  
<?php
// raw data
$data = $_POST['data'];
$slices = explode(",", $data);

// initialize some variables
$sum = 0;
$degrees = Array();
$diameter = 200;
$radius = $diameter/2;

// set up colours array for pie slices (rgb, as percentages of
intensity) // add more to these if you like $colours = array(
 array(0,0,0), 
 array(0,0,1), 
 array(0,1,0), 
 array(1,0,0),
 array(0,1,1), 
 array(1,1,0), 
 array(1,0,1), 
);

// calculate sum of slices
$sum = array_sum($slices);

// convert each slice into corresponding percentage of 360-degree circle
for ($y=0; $y<sizeof($slices); $y++) {
 $degrees[$y] = ($slices[$y]/$sum) * 360;
}

// start building the PDF document
// create handle for new PDF document
$pdf = pdf_new();

// open a file
pdf_open_file($pdf, "chart.pdf");

// start a new page (A4)
pdf_begin_page($pdf, 500, 500);

// set a stroke colour
pdf_setcolor($pdf, "stroke", "rgb", 1, 1, 0);

// draw baseline
pdf_moveto($pdf, 250, 250);
pdf_lineto($pdf, 350, 250);
pdf_stroke($pdf);

for ($z=0; $z<sizeof($slices); $z++)
{
 // set a fill colour
 pdf_setcolor($pdf, "fill", "rgb", $colours[$z][0],
$colours[$z][1], $colours[$z][2]);

 // calculate coordinate of end-point of each arc by obtaining 
 // length of segment and adding radius
 // remember that cos() and sin() return value in radians 
 // and have to be converted back to degrees!
 $end_x = round(250 + ($radius * cos($last_angle*pi()/180))); 
 $end_y = round(250 + ($radius * sin($last_angle*pi()/180)));

 // demarcate slice with line
 pdf_moveto($pdf, 250, 250);
 pdf_lineto($pdf, $end_x, $end_y);

 // calculate and draw arc corresponding to each slice
 pdf_arc($pdf, 250, 250, $radius, $last_angle,
($last_angle+$degrees[$z]));

 // store last angle
 $last_angle = $last_angle+$degrees[$z];

 // fill slice with colour
 pdf_fill_stroke($pdf);
}

// redraw the circle outline
pdf_circle($pdf, 250, 250, 100);
pdf_stroke($pdf);

// end page
pdf_end_page($pdf);

// close and save file
pdf_close($pdf);

?>

Дані, введені у форму, передаються скрипту "pie.php" змінної $data; ці дані згодом діляться на окремі компоненти функцією explode(), і кожне значення присвоюється масиву $slices. Далі в циклі ці числа конвертуються в градуси для круга і для кожного сектора малюється дуга, В кожному проході циклу також обчислюється координати кінцевої точки дуги і малюється сегмент лінії для того, щоб відокремити дугу від решти окружності. Як тільки кругова діаграма намальована, використовується функція pdf_fill_stroke() для заливки її кольором; колір береться з масиву $colours.