Jak udržet vysokou přehlednost skriptů v rozsáhlých projektech a neztratit nic z flexibility designu? Ukážeme si, jak v PHP elegantně produkovat kompletní dokumenty (HTML stránku, XML, e-mail a podobně).

Setkal jsem se s případem, kdy designer udělal vcelku pěkný grafický návrh firemního webu o cca 20 HTML stránkách. Opravdu hezké. Celá prezentace byla vytvořena staticky v HTML. Jakmile se však měla přidat další stránka a mělo se rozšířit menu navigace o další odkaz, byl designer nucen upravit všech těchto 20 stránek – šlo o globální menu nad celou prezentací.

Nasazením prezentace do provozu práce na webu nekončí. V tomto případě musíme přemýšlet, jakým způsobem umožnit snadnou modifikaci obsahu. Představou designera o řešení problému bylo zařazení příkazu include. Menu by se vkládalo ze souboru a změnou tohoto jednoho souboru se tak menu změní na všech stránkách. Cestou určitě je minimalizace duplicit.

OK, ale přece vám tady nebudu ukazovat, jak funguje include. Pro potřeby správy obsahu jsem napsal třídu CONTENT MANAGER. A ihned po představení kódu této třídy sami zjistíte, že možnosti využití jsou opravdu značně široké, ostatně, jako funkce příkazu include samotného.

<?php
// class_contentmanager.php
class content_manager {
    var $CONTENT = array();
    var $FLOW = array();
    var $FLOW_TOP = 1;
    var $RESULT = “;
  function content_manager() {
  }
  function insert_element($order, $content, $file = NULL) {
    if (isset($file) and is_file($content) and is_readable($content)):
      $fcontents = file ($content);
      $fcontents = implode (“, $fcontents);
      $content =& $fcontents;
    endif;
    if (isset($file) and !isset($fcontents)):
      return 0;
    endif;
    if (empty($order)):
      $order = $this->FLOW_TOP;
    endif;
    $con_count = array_push ($this->CONTENT, $content);
    if (is_array($order)):
      foreach($order as $vorder){
        $flo_count = array_push ($this->FLOW, array(‚ORDER’=>$vorder, ‚POINTER’=>($con_count-1)));
        if ($vorder >= $this->FLOW_TOP):
          $this->FLOW_TOP = $vorder + 1;
        endif;
      }
    else:
      $flo_count = array_push ($this->FLOW, array(‚ORDER’=>$order, ‚POINTER’=>($con_count-1)));
      if ($order >= $this->FLOW_TOP):
        $this->FLOW_TOP = $order + 1;
      endif;
    endif;
    return $flo_count;
  }
  function delete_element($index) {
    if (isset($this->FLOW[$index])):
      $tempflow = $this->FLOW[$index];
      unset($this->FLOW[$index]);
      $num = 0;
      foreach($this->FLOW as $key => $value){
        if ($key == $index) continue;
        if ($value[‚POINTER‘]==$tempflow[‚POINTER‘]):
          $num++;
        endif;
      }
      if (empty($num)):
        unset($this->CONTENT[$tempflow[‚POINTER‘]]);
      endif;
    endif;
  }
  function result($ref = NULL) {
    if (!isset($ref)):
      $ref =& $this->RESULT;
    endif;
    $ref = “;
    usort($this->FLOW, ‚usort_content_manager‘);
    foreach($this->FLOW as $value){
      $ref .= $this->CONTENT[$value[POINTER]];
    }
  }
}
function usort_content_manager($a, $b) {
  if ($a[‚ORDER‘] == $b[‚ORDER‘]):
    return 0;
  else:
    return ($a[‚ORDER‘] > $b[‚ORDER‘]) ? 1 : -1;
  endif;
}
?>

Pouhými třemi metodami insert_element, delete_element a result vládne třída CONTENT MANAGER. Podívejme se ovšem ještě před tím na její vlastnosti. Pole $CONTENT si představme jako skladiště elementů obsahu. Budeme-li mít patičku stránky v souboru, bude to z pohledu objektu jeden element obsahu. Každý element je identifikován číslem. Pole $FLOW je dvourozměrné. Rozměrem ‚ORDER‘ se popisuje, jak bude vypadat výsledný tok dokumentu – tedy pořadí elementů obsahu za sebou. Rozměr ‚POINTER‘ představuje odkaz na prvek $CONTENT. Vlastnost $FLOW_TOP udržuje poslední nejvyšší pořadové číslo z $FLOW a konečně $RESULT, odkud získáme výsledek.

Nákres abstrakce

Metoda insert_element má 3 parametry: $order, $content, $file. Prvním argumentem se metodě předá pořadové číslo, druhým element obsahu a třetí (nepovinný), pokud je nenulový, pracuje s druhým parametrem jako s cestou k souboru. První argument může být pole (použití uvidíme na příkladu). Insert_element vrací nový počet prvků ve $FLOW. Vložíme-li například jeden element, můžeme toto číslo (snížené o jedničku) později využít u metody delete_element.

Metoda delete_element má právě jeden parametr. Předáme-li jí číslo, vymaže se element z $FLOW uložený pod tímto číslem. Pokud již z $FLOW neodkazuje jiný element na element obsahu do $CONTENT, je tento element obsahu také smazán!

Metodou result vyprodukujeme výsledek. Ten se uloží do odkazem předané proměnné nebo defaultně $RESULT.

Vedle kódu třídy stojí funkce usort_content_manager. Jde o uživatelskou funkci, hrající klíčovou roli ve funkci usort (viz metoda result).

Můžeme začít experimentovat. Naše stránka bude mít hlavičku, patičku, hlavní navigační menu, tělo, reklamní vložku a pravý pruh (viz například Interval.cz). Pro umělou ‚složitost‘ se rozhodneme ve skriptu dynamicky měnit titulek <TITLE>, navíc hlavní navigační menu bude umístěno také ve spodní části. Dále ať mluví kód příkladu, produkovat budeme HTML stránku.

<?php
// example.php
require_once (‚class.contentmanagement.php‘);
$content_html = new content_manager();
$content_html->insert_element(0, ‚head.html‘, 1);
$content_html->insert_element(0, ‚<title>Úvodní stránka</title>‘);
$content_html->insert_element(0, ‚top.html‘, 1);
$content_html->insert_element(array(4, 8), ‚menu.html‘, 1);
$content_html->insert_element(5, ‚uvod.html‘, 1);
$content_html->insert_element(6, ‚banner.html‘, 1);
$content_html->insert_element(7, ‚rightboxes.html‘, 1);
$content_html->insert_element(0, ‚foot.html‘, 1);
$content_html->result();
print ($content_html->RESULT);
//je-li potřeba ladit…
echo ‚<pre>‘;
print_r($content_html->CONTENT);
print_r($content_html->FLOW);
echo ‚</pre>‘;
?>

Při ladění sledujeme obsah polí $CONTENT a $FLOW. Kód níže nám zařadí navigační menu na začátek a na konec stránky (respektive na pozici 4 a 8).

$content_html->insert_element(array(4, 8), ‚menu.html‘, 1);

Velmi elegantní, co říkáte? Rozsáhlé skripty a rozsáhlé projekty vůbec zpravidla využívají šablonový systém. CONTENT MANAGER by však tento systém neměl nahradit – měl by ho výhodně doplnit. (K dispozici jsou zdrojové kódy i ukázka pro získání lepší představy.)

Starší komentáře ke článku

Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.

Žádný příspěvek v diskuzi

Odpovědět