PHP: strefaphp.net
PHP: strefaphp.net



 
Czy odwiedziłeś już te strony? -
dodał: Vengeance

Opis artykułu dodano: 05-10-2004 22:17
Denerwuje Cię już kod HTML między skryptami PHP? Chciałbyś się go pozbyć ale nie wiesz jak lub twoje sposoby są mało skuteczne? Teraz możesz się go pozbyć ze swojego skryptu, w szybki i "zgrabny" sposób za pomocą parsera szablonów.
Atuty parsera to:
- przejrzystość kodu php po całkowitym oddzieleniu go od kodu HTML itp.
- łatwa zmiana layouta strony - wystarczy podmienić kilka plików
- możliwość wczytania wielu plików z szablonami i nadania im odpowiednich bloków do zamiany, a dopiero poźniejsze sparsowanie całości
- wyświetlanie wyników wszystkich parsowań, pojedyńczego parsowania lub parsowań z pewnego przedziału
Artykuł Przedstawia kolejne etapy tworzenia takiego parsera.
dodał: DarkSpirit | autor: DarkSpirit | czytano: 18857 razy

Inne materiały do artykułu

Tworzymy własny parser szablonów
Dla przykładu, plik z szablonem(szablon.tpl):

Cytat:

<HTML>
<HEAD>
<TITLE>{TITLE}</TITLE>
</HEAD>
<BODY>
{TEXT}
</BODY>
</HTML>

I by go użyć będziemy potrzebowali tylko takiego małego kawałku kodu:

Kod:


<?php
   
// [...] wcześniejsza część skryptu

   
$templates->load('szablon'); // wgrywamy plik z szablonem
   
$templates->blocks[] = array ('TITLE' => $page_title'TEXT' => $text); // ustalamy bloki do zamiany
   
$templates->parse(); // parsujemy kod HTML
   
$templates->show_result(); // wyświetlamy wynik

   // [...] dalsza część skryptu
?>



To było najprostsze zastosowanie mojego parsera. Dodatkowe atuty parsera to:
- możliwość wczytania wielu plików z szablonami i nadania im odpowiednich bloków do zamiany, a dopiero poźniejsze sparsowanie całości
- wyświetlanie wyników wszystkich parsowań, pojedyńczego parsowania lub parsowań z pewnego przedziału

Artykuł Przedstawia kolejne etapy tworzenia takiego parsera.

ETAP 1
Zadanie: Parser zostanie napisany obiektowo(czyt. z zastosowaniem klas), zastanówmy się więc najpierw jakie powinien posiadać funkcje(operacje) i zmienne(atrybuty).

Wynik:
Stałe(definiowane poza klasą):
- F_TPL - przechowuje nazwę katalogu, w którym znajdują się szablony.
Atrybuty:
- $last_loaded - przechowuje nazwę ostatnio wczytamego pliku.
- $unparsed - przechowuje niezamieniony kod stron,
- $parsed - przechowuje zamieniony kod stron,
- $blocks - przechowuje bloki do zamiany.
Operacje:
- load() - wczytuje szablon(kod strony) i zapisuje go jako kolejny element tablicy $unparsed
- parse() - parsuje szablon i zapisuje wynik swojego działania jako kolejny element tablicy $parsed
- show_result() - wyświetla sparsowane szablon, w zależności od podanego parametru, wyświetla jeden szablon, szablony z podanego przedziału, lub jeśli nie podaliśmy parametru wyświetla wszystkie sparsowane szablony.

ETAP 2
Zadanie: Tworzymy kodowy zarys projektu.

Wynik:

Kod:


<?php
   
class Templates
   
{

      var 
$unparsed = array ();

      var 
$parsed = array ();

      var 
$blocks = array();

      var 
$last_loaded

      function 
load()
      {
      } 
#end function load()

      
function parse()
      {
      } 
#end function parse()

      
function show_result()
      {
      } 
#end function show_result()
   
#end class Templates

   
define('F_TPL','tpls/');
?>



ETAP 3
Zadanie: Tworzymy funkcję otwierająca plik z szablonem.

Argumenty funkcji:
- funckja pobiera nazwę pliku do odczytu o rozszerzeniu .tpl

Działanie: Otwieramy plik do odczytu i zapisujemy całą jego zawartość jako kolejny element tablicy $unparsed.

Wykonanie:
1) Sprawdzamy czy ostatnio nie był wczytany ten sam plik, jeśli tak dodajemy nowy element to tablicy $unparsed o wartości ostatnio wczytanego szablonu, jeśli nie kontynuujemy działanie skryptu.
2) Sprawdzamy czy plik istnieje za pomocą funkcji file_exists(), która pobiera jako pierwszy parametr ścieżkę i nazwę pliku, jeśli tak wykonujemy dalszy skrypt, a jeśli nie wyskakuje błąd.
3) Blokujemy plik do odczytu za pomocą funkcji flock(), która jako pierwszy parametr pobiera identyfikator pliku, a jako drugi cyfrę oznaczająca dane działanie(dla zablokowania pliku jest to liczba 2).
4) Otwieramy plik za pomocą funkcji fopen(), która jako pierwszy parametr pobiera ścieżkę i nazwę pliku do otworzenia, a jako drugi tryb otworzenia pliku(w tym przypadku tryb odczytu: r od read).
5) Wczytyjemy całą zawartość pliku z szablonem za pomocą funkcji fread, która jako pierwszy parametr pobiera identyfikator pliku, a jako drugi wielkość danych jaką ma pobrać funkcja, po użyciu funkcji file_size() działającej na tym pliku, otrzymamy wielkość pliku, która zostanie zwrócona i wstawiona jako drugi parametr.
6) Zapisujemy wczytaną wartość jako nowy element w tablicy $unparsed.
7) Odblokowujemy plik do odczytu za pomocą funkcji flock(), która jako pierwszy parametr pobiera identyfikator pliku, a jako drugi cyfrę oznaczająca dane działanie(dla odblokowania pliku jest to liczba 3).

Wynik:

Kod:


<?php
      
function load($plik)
      {
         if(
$plik == $this->last_loaded)
         {
            
$this->unparsed[] = end($this->unparsed);
         }
         elseif(
file_exists(F_TPL.$plik.'.tpl'))
         {
            
$file = @fopen(F_TPL.$plik.'.tpl',r);
            
flock($file2);
            
$this -> unparsed[] = fread($file,filesize(F_TPL.$plik.'.tpl'));
            
flock($file3);
            
$this->last_loaded $plik;
         }
         else
            echo 
'Plik ' .$plik' nie istnieje.';
      } 
#end function load()
?>



ETAP 4
Zadanie: Tworzymy funkcję parsującą szablon.

Działanie: Zamieniamy bloki między { i } na tekst podany w tablicy $blocks.

Wykonanie:
1) Wyszukujemy w szablonie ciągi znaków znajdujących się pomiędzy { i } i zapisujemy je w tablicy $found, za pomocą funkcji preg_match_all, która wykorzystuje perlowskie wyrażenia regularne, a znalezione ciągi zapisuje do tablicy.
2) Dla wszytskich znalezionych bloków, wyszukuje treść do zamiany z wielo wymiarowej tablicy $blocks o wymiarze odpowiednim dla danego szablonu i zamienia ją za bloki w szablonie za pomocą funkcji str_replace().
3) Sparsowany szablon zapisuje do zmiennej $template.
4) Po sparsowaniu wszystkich bloków w szablonie zapisuje w całości sparsowany szablon jako nowy element tablicy $parsed.

Czynności od 1 do 4 przeprowadzane są dla każdego z szablonów.

Funkcja foreach() działa w ten sposób iż każdy element tablicy zapisuje do nowej tablicy(w tym przypadku $this->unparsed as $template) i dla każdego elementu z nowej tablicy wykonuje odpowiedni kod zawarty między { i }.

Wynik:

Kod:


<?php
      
function parse()
      {
         
$i=0;
         foreach (
$this->unparsed as $template)
         {
            
$found = array();
            if(
preg_match_all("#\{(.+?)\}#is"$template$found))
            {
               foreach(
$found[1] as $block)
               {
                  
$block_name '{'.$block.'}';
                  
$block_values $this -> blocks[$i][$block];
                  
$template str_replace($block_name$block_values$template);
               }
            }
            
$this -> parsed[] = $template;
            
$i++;
         }
      } 
#end function parse()
?>



ETAP 5
Zadanie: Tworzymy funkcję wyświetlająca wyniki parsowania.

Działanie: Wyświetlamy wszystkie sparsowane szablony lub wyświetlamy jeden sparsowany szablon, lub wyświetlamy szablony z podanego przedziału.

Wykonanie:
1) Sprawdzamy czy dane o wyświetlaniu szablonów są poprawne, tzn. czy liczba zaczęcie jest mniejsza od liczby zakończenia, czy liczby zakończenia i początku są większe lub równe 0 i czy liczby końca nie jest większa od liczby wszystkich szablonów, jeśli wszystko jest poprawne wyświetlamy szablony z podanego przedziału.
2) Sprawdzamy czy liczba wyświetlonego szablonu jest równa lub większa od 0 i mniejsza lub równa od liczby szablonów, jeśli tak zostaje wyświetlony podany szablon.
3) W przeciwnym wypadku zostają wyświetlone wszystkie szablony od początku do końca.

Wynik:

Kod:


<?php
      
function show_result($which="all",$to=0)
      {
         if(
$which >= && $to >= && $to <= count($this->parsed) && $which != 'all')
         {
            if(
$which $to)
            {
               while(
$which <= $to)
               {
                  echo 
$this->parsed[$which];
                  
$which++;
               }
            }
            else
            {
               while(
$which >= $to)
               {
                  echo 
$this->parsed[$which];
                  
$which--;
               }
            }
         }
         elseif(
$which != 'all')
         {
            echo 
$this->parsed[$which];
         }
         else
         {
            foreach(
$this->parsed as $parsed)
            {
               echo 
$parsed;
            }
         }
      } 
#end function show_result()
?>



No to całą klasę mamy napisaną, teraz przejdźmy do praktycznego zastosowania naszej klasy. Oto cała nasza klasa:

Kod:


<?php
   
class Templates
   
{

      var 
$unparsed = array ();

      var 
$parsed = array ();

      var 
$blocks = array();

      var 
$last_loaded;

      function 
load($plik)
      {
         if(
$plik == $last_loaded)
         {
            
$this->unparsed[] = end($this->unparsed);
         }
         elseif(
file_exists(F_TPL.$plik.'.tpl'))
         {
            
$file = @fopen(F_TPL.$plik.'.tpl',r);
            
flock($file2);
            
$this -> unparsed[] = fread($file,filesize(F_TPL.$plik.'.tpl'));
            
flock($file3);
            
$this->last_loaded $plik;
         }
         else
            echo 
'Plik ' .$plik' nie istnieje.';
      } 
#end function load()

      
function parse()
      {
         
$i=0;
         foreach (
$this->unparsed as $template)
         {
            
$found = array();
            if(
preg_match_all("#\{(.+?)\}#is"$template$found))
            {
               foreach(
$found[1] as $block)
               {
                  
$block_name '{'.$block.'}';
                  
$block_values $this -> blocks[$i][$block];
                  
$template str_replace($block_name$block_values$template);
               }
            }
            
$this -> parsed[] = $template;
            
$i++;
         }
      } 
#end function parse()

      
function show_result($which="all",$to=0)
      {
         if(
$which >= && $to >= && $to <= count($this->parsed) && $which != 'all')
         {
            if(
$which $to)
            {
               while(
$which <= $to)
               {
                  echo 
$this->parsed[$which];
                  
$which++;
               }
            }
            else
            {
               while(
$which >= $to)
               {
                  echo 
$this->parsed[$which];
                  
$which--;
               }
            }
         }
         elseif(
$which != 'all')
         {
            echo 
$this->parsed[2];
         }
         else
         {
            foreach(
$this->parsed as $parsed)
            {
               echo 
$parsed;
            }
         }
      } 
#end function show_result()
   
#end class Templates
   
define('F_TPL','tpls/');
?>



A to jej praktyczne zastosowanie


Kod:


<?php
   
include('templates.class.PHP'); // wczytujemy plik z klasą
   
$templates = new Templates// tworzymy nowy obiekt klasy Templates
   
$templates->load('main_category'); // wczytujemy nowy szablon
   
$tempaltes->blocks[] = array ('CATEGORY' => 'Kategoria'); // bardzo ważne by po każdym wczytaniu dodać nową tablicę do tablicy $blocks
                                                             // nazwę bloku wpisujemy po lewej stronie bez klamer, a wartość do zamiany po =>
                                                             // jeśli nie potrzebujemy zamieniać żadnych bloków wystarczy wpisać "" => ""
   
$templates->load('menu');
   
$templates->blocks[] = array ('' => '');
   
$templates->parse(); // parsujemy szablony
   
$templates->show_result(); // wyświetlamy wyniki
?>



Powodzenia w dalszej modyfikacji i używaniu skrypty, wszelkie błędy i nie jasności proszę zgłaszać na forum.

Cały kod źródłowy wraz z testowymi szablonami i artykułem dostępny jest w dziale download=>Skrypty zespołu phpworld
PHP: strefaphp.net
wyślij email informacje forum download skrypty katalog kursy porady artykuły home współpraca reklama kontakt