online: 6; azi: 892; total: 52898 Webdesign - Phpmysql - 49

Creare PDF cu PHP (2)

  • Aceasta lectie prezinta cateva lucruri mai avansate din lucrul cu FPDF

In prima parte (lectia 34) au fost prezentate lucrurile de baza prin care puteti crea un document PDF cu un continut simplu, folosind clasa FPDF.
In aceasta lectie sunt prezentate aspecte mai avansate din crearea paginilor PDF cu FPDF. Acestea necesita cunostinte medii de lucru cu functii si clase in PHP.

1. Header, Footer si Nr. pagina

Cand aveti un document PDF cu mai multe pagini, puteti crea printr-o singura funtie un continut care sa fie afisat in partea de sus (Header) sau de jos (Footer) a fiecarei pagini. De asemenea este util sa afisati si numarul paginilor. Toate acestea le puteti crea relativ usor cu functiile clasei FPDF.
Pentru obtinerea numarului paginii curente se foloseste metoda PageNo(), iar ca sa obtineti numarul total de pagini se foloseste metoda AliasNbPages() care defineste un alias pt. numarul total de pagini, acest alias poate fi numele unui argument a functiei sau daca nu e precizat, default e {nb}, si va fi inlocuit la inchiderea crearii documentului PDF cu numarul total de pagini.

Pentru adaugarea unui Header sau Footer in fiecare pagina se foloseste metoda Header() respectiv Footer() definite intr-o clasa extinsa (copil) a clasei FPDF. Aceasta clasa copil trebuie creata de dv. inaintea definirii obiectului de lucru, iar acest obiect va fi creat folosind sintaxa new Clasa_copil() (in loc de "new FPDF()"), unde "Clasa_copil" e numele clasei extinse in care ati definit metodele Header() sau /si Footer(). Aceste metode nu mai trebuiesc apelate dupa crearea obiectului deoarece sunt apelate automat de "AddPage()"
Ca sa intelegeti mai bine, studiati exemplul urmator. Acesta va crea un document PDF cu 2 pagini, fiecare avand acelasi Header iar in Footer este afisat nr. pagina curenta si nr. total pagini.

<?php 
include('fpdf.php');  // Include clasa FPDF

// Creaza clasa copil a clasei de baza FPDF
class PDF extends FPDF {
  // Definirea Header-ului
  function Header() {
    $this->SetFont('Arial','B',15);	// Seteaza Fontul Bold 15
    $this->Cell(80);			// Muta pozitia in dreapta, 80mm
    $this->Cell(40,10,'Titlu Header',1,0,'C');	// Adauga un text
    $this->Ln(20);				// Adauga rand nou
  }

  // Definirea Footer-ului
  function Footer() {
    $this->SetY(-15);		// Seteaza pozitia la 15mm pe verticala fata de subsolul paginii
    $this->SetFont('Arial','I',8);	// Seteaza Fontul Italic 8

    //Adauga o celula cu text ce contine nr. paginii curente si nr. total de pagini definit prin 'alias' (care va fi atributul lui AliasNbPages())
    $this->Cell(0,10,'Page '.$this->PageNo().'/nr_pgs',0,0,'C');
  }
}

// Definirea obiectului prin apelarea clasei extinse create mai sus
$pdf=new PDF();

$pdf->AliasNbPages('nr_pgs');		// Seteaza un alias care va prelua nr. total de pagini
$pdf->AddPage();				// Initializeaza adaugarea paginilor

// Seteaza un font si adauga mai multe linii de text pt. a depasi o pagina
$pdf->SetFont('Times','',12);
for($i=1; $i<=35; $i++) $pdf->Cell(0,10,'Linia de text numarul '.$i,0,1);

$pdf->Output();			// Trimite datele de iesire
?>
		
- In functiile "Header()" si "Footer()" din clasa copil PDF puteti adauga si alte functii PHP sau sa apelati cu "$this->" si alte metode ale clasei FPDF (imagini, culori) pentru a crea continutul dorit. Observati ca metodele "Header()" si "Footer()" nu au fost apelate dupa obiectul creat.
- Pentru atributul metodei "AliasNbPages()" (aici 'nr_pgs') puteti folosi orice nume doriti, dar sa tineti cont ca acesta reprezinta numarul total de pagini.

2. Pagina noua si link-uri interne

Cand continutul pe care doriti sa-l adaugati in documentul PDF depaseste lungimea paginii, va fi creata automat o alta pagina, dar sunt cazuri cand doriti crearea intentionata a uneia sau mai multor pagini noi.
Pentru crearea unei pagini noi puteti folosi din nou metoda AddPage(), aceasta va forta adaugarea unei noi pagini.

Cand documentul PDF este mare, cu multe pagini, este util sa folositi link-uri interne care sa redirectioneze printr-un click catre oricare locatie definita de dv. in document. Acest lucru il puteti face folosind doua metode ale clasei FPDF: AddLink() si SetLink().
Prima data folositi AddLink() ca sa atribuiti unei variabile valoarea de link intern, apoi in locatia sau pagina unde doriti sa deschida acest link apelati metoda SetLink() si intre parantezele ei adaugati variabila setata pentru link-ul intern respectiv.
Aceeasi variabila o folositi ca atribut URL si pentru textul, celula sau imaginea care va afisa link-ul (pe care se va da click).

Ca sa intelegeti mai bine studiati exemplul urmator:

<?php
include('fpdf.php');  // Include clasa FPDF

// Se defineste clasa extinsa, pt. adaugarea nr. pagina in Footer
class PDF extends FPDF {
  // Definirea Footer-ului
  function Footer() {
    $this->SetY(-15);		// Seteaza pozitia la 15mm pe verticala fata de subsolul paginii
    $this->SetFont('Arial','I',8);	// Seteaza Fontul Italic 8

    // Adauga o celula cu text ce contine nr. paginii curente
    $this->Cell(0,10,'Page '.$this->PageNo(),0,0,'C');
  }
}

$pdf = new PDF();		// Creaza obiectul de lucru
$pdf->AddPage();		// Initializeaza prima pagina
$pdf->SetFont('Arial','',15);	// Defineste fontul

// Seteaza variabilele pt. 2 link-uri interne
$pag1 = $pdf->AddLink();
$pag3 = $pdf->AddLink();

$pdf->Write(5,'Textul din prima pagina a documentului PDF, cu link intern catre pagina 3,
 adaugat prin alta apelare a metodei Write() ce contine textul si variabila definita ca link intern catre ');

$pdf->SetFont('','U');		// Seteaza fontul pt. link
$pdf->Write(5,'pagina 3',$pag3);	 // Adauga link-ul
$pdf->SetFont('');		// Modifica din nou fontul

// Seteaza destinatia link-ului intern din variabila $pag1
$pdf->SetLink($pag1);

// Adauga o noua pagina
$pdf->AddPage();
$pdf->Write(5,'Textul din a doua pagina');

// Adauga o alta pagina
$pdf->AddPage();
$pdf->Write(5,'Textul din a treia pagina, link catre prima pagina, ');
$pdf->SetFont('','U');		// Seteaza fontul pt. link
$pdf->Write(5,'click aici',$pag1);	// Adauga link-ul

// Seteaza destinatia link-ului intern din variabila $pag3
$pdf->SetLink($pag3);

$pdf->Output();			// Trimite datele de iesire
?>
		
- Am adaugat o extindere a clasei FPDF ca sa fie adaugat un Footer in care sa se afiseze numarul paginii.

3. Creare tabel

Ca sa creati un tabel intr-un document PDF trebuie sa creati cate o celula pentru fiecare casuta a tabelului si sa le asezati (definiti) astfel incat sa formeze un tabel. Pentru aceasta cel mai indicat este folosirea matricelor.
In exemplul urmator este prezentat si explicat un script care preia niste date dintr-un fisier text (aici state.txt) si le afiseaza intr-un document PDF sub forma de tabel. Datele din fisier sunt linii de text care contin numele unor state, capitala, suprafata si populatie; separate prin caracterul punct si virgula (;). Astfel, va fi creat un tabel cu 4 coloane.
Explicatiile necesare le gasiti in script, studiati cu atentie comentariile adaugate, acestea va ajuta sa intelegeti modul de lucru si rolul fiecarei linii de cod.

<?php
include('fpdf.php'); 	 // Include clasa FPDF

// Creaza clasa copil a clasei de baza FPDF
class PDF extends FPDF {
  // Peia datele din fisier si le separa
  function LoadData($file) {
    // Citeste fiecare liniile din fisier, primit ca argument
    // Separa datele cu "explode()" si le adauga intr-o matrice
    $lines = file($file);

    // Defineste matricea $data care va contine pt. fiecare element cate o matrice cu datele liniei
    $data = array();
    foreach($lines as $line) $data[]=explode(';',trim($line));

    return $data;		// Returneaza matricea cu datele separate
  }

  // Creaza celulele in forma unui tabel, cu datele din matrice
  // Primeste ca argumente variabilele ce contin textul pt. header si datele din matrice
  function FancyTable($header,$data) {
    //Defineste grafica pt. Header-ul tabelului
    $this->SetFillColor(254,90,110);
    $this->SetTextColor(255);
    $this->SetDrawColor(128,0,0);
    $this->SetLineWidth(.3);
    $this->SetFont('','B');

    $w = array(40,35,40,45);			// Matricea cu lungimea fiecarei coloane

    // Afiseaza in linie cate o celula de text (argumentul cinci este 0)
    for($i=0; $i<count($header); $i++) $this->Cell($w[$i],7,$header[$i],1,0,'C',true);

    $this->Ln();			// Adauga linie noua dupa header

    //Defineste un fondul si culoarea pt. text
    $this->SetFillColor(224,235,255);
    $this->SetTextColor(0);
    $this->SetFont('');

    // Seteaza o variabila care determina daca celula va avea fondul definit sau nu
    $fill = false;

    // Pentru fiecare matrice principala din $data creaza cate o linie cu 4 celule
    // In fiecare celula adauga datele din elementele sub-matricei curente (formata cu explode())
    // 'LR' reprezinta bordura doar in stanga si dreapta (Left, Right)
    foreach($data as $row) {
      $this->Cell($w[0],6,$row[0],'LR',0,'L',$fill);
      $this->Cell($w[1],6,$row[1],'LR',0,'L',$fill);
      $this->Cell($w[2],6,$row[2],'LR',0,'R',$fill);
      $this->Cell($w[3],6,$row[3],'LR',0,'R',$fill);

      $this->Ln();			// Adauga rand nou dupa fiecare linie
      $fill = !$fill;		// Alterneaza 'true', 'false' variabila ce determina includerea fondului
    }

    // Adauga o celula goala pt. cu lungimea totala a coloanelor si o bordura
    // Aceasta e necesara pt afisarea liniei de sfarsit a tabelului
    $this->Cell(array_sum($w),0,'','T');
  }
}

$pdf = new PDF();			// Creaza obiectul de lucru

// Matricea cu textul header a fiecarei coloane
$header = array('State','Capitala','Suprafata','Populatie (mii)');
$data=$pdf->LoadData('state.txt');		// Apeleaza metoda care preia datele din fisier

$pdf->SetFont('Arial','',14);
$pdf->AddPage();
$pdf->FancyTable($header,$data);		// Apeleaza metoda care aseaza celulele in forma de tabel

$pdf->Output();
?>
		

Continutul fisierului "state.txt" este urmatorul:
Austria; Vienna; 83859; 8075
Belgium; Brussels; 30518; 10192
Denmark; Copenhagen; 43094; 5295
Finland; Helsinki; 304529; 5147
France; Paris; 543965; 58728
Germany; Berlin; 357022; 82057
Greece; Athens; 131625; 10511
Ireland; Dublin; 70723; 3694
Italy; Roma; 301316; 57563
Luxembourg; Luxembourg; 2586; 424
Netherlands; Amsterdam; 41526; 15654
Portugal; Lisbon; 91906; 9957
Spain; Madrid; 504790; 39348
Sweden; Stockholm; 410934; 8839
United Kingdom; London; 243820; 58862

8. Parsare cod HTML

In acest ultim exemplu este prezentat un script care recunoaste etichetele html <b>, <i>, <u>, <a> si <br> sau <br />.
Normal, clasa FPDF creaza documentul PDF cu textul asa cum este scris, fara a recunoaste tag-urile, totusi, de multe ori este necesara aceasta facilitate si poate fi creata cu functii specifice adaugate intr-o clasa extinsa.
Aceasta modalitate consta in lucru cu functii pentru siruri. Pe scurt, trebuie create functii care sa recunoasca tag-urile dorite din sir, apoi, in functie de semnificatia acestor tag-uri, sa apeleze metodele clasei care sa defineasca stilul textului afisat in pagina PDF.
Studiati clasa extinsa creata in exemplul de mai jos, pe care o puteti copia si folosi in programele dv.

<?php
include('fpdf.php');  // Include clasa FPDF

// Creaza clasa extinsa a clasei de baza FPDF
class PDF extends FPDF {
  // Definirea variabilei pt. lucru cu adresa URL
  var $HREF;

  // Functia care scrie textul si recunoaste tagu-urile HTML
  function WriteHTML($html) {
    // Inlocuieste cu spatiu linia noua si parseaza tag-ul HTML
    $html = str_replace("\n",' ',$html);
    $a = preg_split('/<(.*)>/U',$html,-1,PREG_SPLIT_DELIM_CAPTURE);
    foreach($a as $i=>$e) {
	  if($i%2==0) {
	    // Daca in tag e recunoscut href
		if($this->HREF) $this->PutLink($this->HREF,$e);
		else $this->Write(5,$e);
      }
      else {
        // Daca este eticheta de inchidere a tag-ului
		if($e[0]=='/') $this->CloseTag(strtoupper(substr($e,1)));
        else {
          // Extrage atributele
          $a2 = explode(' ',$e);
          $tag = strtoupper(array_shift($a2));
          $attr=array();
          foreach($a2 as $v) {
            if(preg_match('/([^=]*)=["\']?([^"\']*)/',$v,$a3))
              $attr[strtoupper($a3[1])] = $a3[2];
          }
          $this->OpenTag($tag,$attr);
        }
      }
    }
  }

  // Functia pt. determinarea actiunii in functie de tag-ul HTML recunoscut
  function OpenTag($tag,$attr) {
    // Daca tag-ul este B, I sau U
    if($tag=='B' || $tag=='I' || $tag=='U') $this->SetStyle($tag,true);
	// Daca tag-ul e A
    if($tag=='A') $this->HREF=$attr['HREF'];
	// Daca tag-ul e BR
    if($tag=='BR') $this->Ln(5);
  }

  // Functia pt. actiunea la inchiderea tag-ului
  function CloseTag($tag) {
    // Daca tag-ul inchis este B, I sau U
    if($tag=='B' || $tag=='I' || $tag=='U') $this->SetStyle($tag,false);
	// Daca tag-ul inchis e A
    if($tag=='A') $this->HREF='';
  }

  // Functia pt. setarea stilului textului in functie de tipul tag-ului B, I, U
  function SetStyle($tag,$enable) {
    // Seteaza stilul fontului in functie de tag-ul B, I sau U
    $this->$tag+=($enable ? 1 : -1);
    $style = '';
    foreach(array('B','I','U') as $s) {
      if($this->$s>0) $style.=$s;
    }
    $this->SetFont('',$style);
  }

  // Functia pt. adaugarea link-ului
  function PutLink($URL,$txt) {
    // Seteaza fontul specific link si apeleaza metoda Write() cu atribut pt. URL
    $this->SetTextColor(0,0,255);
    $this->SetStyle('U',true);
    $this->Write(5,$txt,$URL);
    $this->SetStyle('U',false);
    $this->SetTextColor(0);
  }
}

// Variabila ce contine textul cu elemente HTML
$html = 'Text care contine tag-uri HTML a caror stil va fi recunoscut si modificat pentru PDF, pentru a fi similar cu stilul afisat in pagina HTML.<br />
Linie noua adaugata cu BR, stilurile recunoscute: <b>bold</b>, <i>italic</i>, <u>underlined</u>, sau <b><i><u>toate la un loc</u></i></b>!<br><br>
	Link adaugat prin recunoasterea tag-ului "A" specific pt. link-uri, <a href="http://www.marplo.net/php-mysql/">Curs PHP - MySQL</a>';

$pdf = new PDF();
$pdf->AddPage();
$pdf->SetFont('Arial','',14);

// Apeleaza metoda WriteHTML() creata in clasa extinsa
// transferand ca argument variabila $html
$pdf->WriteHTML($html);

$pdf->Output();
?>
		
- Aceasta clasa extinsa recunoaste si transforma doar tag-urile HTML <b>, <i>, <u>, <a> si <br> sau <br />; daca in sir sunt si alte tag-uri acestea nu vor fi adaugate.
- Studiati si documentatia si tutorialul de pe site-ul oficial www.fpdf.org.