Листинг 1
class Price extends FPDF {
function PrintTitle($title,$image,$company) {
//Выводим логотип
$this->Image($image,6,6,40,20);
//Устанавливаем шрифт для наименования компании
$this->SetFont('TimesNewRomanPSMT','',20);
//Выводим наименование компании
$this->Cell(210,4,$company,0,0,'C');
//Переходим на следующую строку
$this->Ln();
//Переходим на следующую строку
$this->Ln();
//Делаем отступ от левого края (рисуя прозрачную ячейку)
$this->Cell(37);
//Устанавливаем цвет заливки следующих ячеек (R,G,B)
$this->SetFillColor(209,204,244);
//Устанавливаем шрифт для наименования документа
$this->SetFont('TimesNewRomanPSMT','',12);
//Выводим наименование документа
$this->Cell(150,8,$title,0,0,'C',1);
//Переходим на следующую строку
$this->Ln();
}
}
?>
Листинг 2
define('FPDF_FONTPATH','font/');
require('fpdf.php');
require('price.class.php');
$price = new Price();
$price->Open();
$price->AddFont('TimesNewRomanPSMT','','times.php');
//Добавляем страничку в документ
$price->AddPage();
//Выводим заголовок, используя написанный нами метод в файле класса
//price.class.php
$price->PrintTitle('Прайс-лист','logo.jpg','Компания "ALKO SELL"');
//Выводим документ в браузер
$price->Output();
?>
В этом файле мы столкнулись еще с несколькими методами класса FPDF. Необходимо заметить, что документ сначала создается в буфере и лишь потом, при вызове метода Output(), выводится в браузер. Поэтому общая схема работы с документом следующая: создаем в буфере документ методом Open(), затем для работы добавляем в этот документ страничку методом AddPage(), формируем содержимое документа различными методами типа Cell() и, наконец, выводим его из буфера в браузер. Если у вас установлен adobe acrobat версии не ниже 5.0, то при запуске price.php в браузере должен открыться документ price.pdf (в Internet Explorer) или сформируется документ doc.pdf для скачивания (в Opera).
Этот документ пока не представляет собой практической ценности, однако на его примере мы разобрали основы вывода статических данных в документ .PDF.
Подключаем источник данных
Перейдем к самому интересному - динамическому формированию содержимого документа. Именно этой возможностью и ценен для РНР разработчика класс FPDF. Я уже говорил выше, что здесь мы рассмотрим вариант получения данных из CSV файла.
Как указано в нашем коротком техническом задании, тело прайс-листа должно состоять из трех граф: наименование товара, розничная цена и оптовая цена. Соответственно, подготовим и файл данных следующего вида:
Пиво "Балтика";15.00;13.45
Пиво "Оболонь";14.00;12.30
Водка "Nemiroff", 1 л.;100.00;89.45
Сохраним его как price.csv. Конечно, в реальном прайс-листе товарных позиций и граф будет больше.
Возможны так же деления по группам товаров (например "пиво", "водка", "вино"), но в данном конкретном примере попробуем рассмотреть упрощенную версию (количество записей можно увеличить).
Перед нами встает необходимость получить данные динамически и представить их в виде обыкновенной таблицы в три колонки, с заголовками колонок (столбцов). Перед созданием экземпляра объекта Price добавим инициализацию массива заголовков (соберем все заголовки в массив):
$header = array("Наименование","Розн.","Опт.");
Далее нам понадобится еще больше расширить класс Price (унаследованный от класса FPDF) методами LoadData() и ImprovedTable(). Первый метод должен будет извлекать данные из CSV файла в массив $data, а второй метод пригодится для отрисовки таблицы с данными из этого массива. Рассмотрим метод LoadData() для класса Price.
function LoadData($file) {
//Получаем данные в массив строк
$lines=file($file);
$data=array();
//Разделяем столбцы каждой строки по точке с запятой.
foreach($lines as $line)
$data[]=explode(';',chop($line));
//Возвращаем массив с данными
return $data;
}
Вставим этот код в файл класса price.class.php. Теперь перейдем к рассмотрению метода ImprovedTable().
Вот его код:
function ImprovedTable($header,$data) {
//Указываем ширину столбцов
$w=array(100,40,40);
//Выводим заголовки столбцов
for($i=0;$i $this->Cell($w[$i],7,$header[$i],1,0,'C');
$this->Ln();
//Выводим данные
//Сначала установим шрифт для данных
$this-> SetFont('TimesNewRomanPSMT','',8);
foreach($data as $row)
{
/*Первый параметр Cell() - ширина столбца, указанная ранее в массиве $w, второй параметр - высота столбца, третий параметр - строка для вывода, LRBT - означает прорисовку границ со всех сторон ячейки (Left, Right, Bottom, Top). Можно также указать выравнивание в ячейке по правому краю ('R') */
//Рисуем ячейку наименования товара
$this->Cell($w[0],6,$row[0],'LRBT');
//Рисуем ячейку розничной цены
$this-> Cell($w[1],6,number_format($row[1]),'LRBT',0,'R');
//Рисуем ячейку оптовой цены
$this-> Cell($w[2],6,number_format($row[2]),'LRBT',0,'R');
//Переходим на следующую строку
$this->Ln();
}
//Closure line
$this->Cell(array_sum($w),0,'','T');
}
Вставим и этот метод в код класса Price. Теперь, когда мы обросли двумя новыми методами, попробуем их применить. Изменим код нашего главного файла (листинг 3).
Можно смотреть на промежуточный результат. Это практически все, чего мы хотели достичь.
Добавим только небольшую деталь - номера страниц с указанием их общего числа в нижней части каждой страницы. Ведь наш источник данных может состоять не из трех записей, а, например, из ста.
Для этого необходимо организовать вывод "подвала" (footer) на каждой странице. С этой целью напишем метод Footer() нашего класса Price. Следует отметить, что методы Footer() и Header() заранее прописаны в классе FPDF и вызываются автоматически при выполнении метода AddPage() и Close().
По умолчанию они пустые, но их можно определить в своих наследуемых классах, при этом ни Footer() ни Header() не потребуется явно вызывать из приложения. Добавим в класс Price() следующий код метода:
function Footer() {
//Позиционирование в 1.5 см от нижней границы
$this->SetY(-15);
//TimesNewRomanPSMT italic 8
$this->SetFont('TimesNewRomanPSMT','',8);
//Номер страницы
$this->Cell(0,10,'Страница '.$this->PageNo().'/{nb}',0,0,'C');
}
Листинг 3
define('FPDF_FONTPATH','font/');
require('fpdf.php');
require('price.class.php');
$header = array("Наименование товара","Розн. цена","Опт. цена");
$price=new Price();
$price->Open();
//Получим массив данных из файла в $data
$data = $price->LoadData("price.csv");
$price->AddFont('TimesNewRomanPSMT','','times.php');
$price->AddPage();
$price->SetFont('TimesNewRomanPSMT','',12);
$price->PrintTitle('Прайс-лист','logo.jpg','Компания "ALKO SELL"');
//Нарисуем таблицу. Аргументами метода являются массив наименований
// столбцов и массив данных из файла price.csv
$price->ImprovedTable($header,$data);
$price->Output();
?>
Теперь этот метод будет автоматически исполняться при вызове метода AddPage(). Для корректной работы необходим последний штрих - вызов из файла приложения (price.php) метода $price->AliasNbPages() перед $price->AddPage().
AliasNbPages([string alias])
При написании метода Footer() мы использовали также PageNo(), метод, возвращающий номер текущей страницы и параметр {nb}, который по умолчанию будет заменен цифрой общего количества страниц в текущем документе. Документ готов, и перед нами встает необходимость его вывода в браузер.
Вывод в браузер
По идее, существует всего два варианта вывода документа в браузер - открытие (если установлен adobe acrobat) и скачивание без непосредственного открытия. В классе FPDF выводом документа в браузер управляет метод Output(). В нашем примере мы использовали этот метод без дополнительных аргументов. Однако документация к FPDF приводит следующий формат его записи:
Output([string file [, boolean download]])
Метод предназначен для сохранения PDF документа в локальный файл или для непосредственного вывода в браузер (если установлена программа просмотра PDF файлов).
Аргумент file означает имя файла. Если таковое отсутствует, то производится попытка открыть документ в окне браузера. Если аргумент file определен, то аргумент download указывает, что файл должен быть сохранен на сервере (значение false) или у пользователя (при установке true выводится диалог "Сохранить как").
Соответственно, можно выделить три варианта написания метода Output() для нашего документа. Первый - Output() - пытается открыть документ в окне браузера. Второй вариант написания выведет у пользователя диалоговое окно "Сохранить как" и предложит скачать документ на его диск - Output("AlkoPrice.pdf", true). И, наконец, третий вариант просто сохранит документ на локальном для скрипта сервере - Output("AlkoPrice.pdf",false) или просто Output("AlkoPrice.pdf"), так как по умолчанию атрибут download всегда имеет значение false.
Стоит отдельно рассмотреть компрессию полученного файла. По умолчанию будет произведена попытка его "ужать" средствами Zlib. Это расширение (extension) должно быть установлено в системе. Если установка не была произведена, то документ получится не сжатым, и будет весить немного больше.
Автор: А. Олищук
Источник: PHP в деталях |