Tutorial: Cum sa creezi un sistem de teme in PHP

In primul rand vom crea o noua pagina (*.html) pe care o vom modifica in functie de ceea ce vrem.

template.page.html
<html>
<head>
  <title>{titlu}</title>
</head>

<body>
  <a href="link.html">{link_name}</a>

  <!-- BEGIN BLOCK nume_block1 -->
  Aici vom scrie ceva care va intra intr-o bucla (loop) {vars_block1}
  <!-- END BLOCK nume_block1 -->

  Aici putem avea orice; tabele, imagini ...

  <!-- BEGIN BLOCK nume_block2 -->
  Aici vom scrie ceva care va intra intr-o alta bucla (loop) {vars_block2}
  <!-- END BLOCK nume_block2 -->
</body>
</html>

Creem clasa:

<?php
class template
{
    
// class functions and vars
}
?>

Vom crea o noua functie care sa salveze tot continutul paginii intr-o variabila; Variabila o vom numi file_contents
Declaram variabila:

public $file_contents;
function 
set_file($file_name)
{
    
$this->file_contents implode(""file($file_name));
}


Dupa ce executam functia

set_file('template.page.html');

Tot ce contine pagina template.page.html va fi salvat in $this->file_contents.
Acum trebuie sa scoatem din $file_contents toate blocurile si le salvam intr-o noua variabila $this->blocks.

public $blocks;
function 
get_blocks($block_name)
{
    
// salvam intr-o variabila partile din $this->file_contents si schimbam fiecare block cu <!-- numeblock_parsed -->
    // in felul asta putem opera fiecare block in parte si il vom scrie in pagina dupa ce este complet
    
$page explode("<!-- BEGIN BLOCK $block_name -->"$this->file_contents);

    
// modificam $this->file_colntents (scoate blockul si scrie in locul lui <!-- block_name_parsed -->)
    
$this->file_contents $page[0]."<!-- {$block_name}_parsed -->";

    
// scoatem blockul complet
    
$page explode("<!-- END BLOCK $block_name -->"$page[1]);

    
// completam $this->file_contents cu restul datelor (ce este dupa <!-- END BLOCK $block_name -->)
    
$this->file_contents.= $page[1];

    
// salvam in $this->blocks blockul specificat
    
$this->blocks[$block_name] = $page[0];
}

Dupa executarea functiei:

$this->get_blocks('nume_block1');

Vom avea:

$this->file_contents '
<html>
<head>
    <title>{titlu}</title>
</head>

<body>
    <a href="link.html">{link_name}</a>
    
    <!-- nume_block1_parsed -->
    
    Aici putem avea orice; tabele, imagini ...
    
    <!-- BEGIN BLOCK nume_block2 -->
        Aici vom scrie ceva care va intra intr-o alta bucla (loop) {vars_block2}
    <!-- END BLOCK nume_block2 -->
</body>
</html>'
;

$this->blocks['nume_block1'] = 'Aici vom scrie ceva care va intra intr-o bucla (loop) {vars_block1}';

Dupa executarea functiei:

$this->get_blocks('nume_block2'); 

Vom avea:

$this->file_contents '
<html>
<head>
    <title>{titlu}</title>
</head>

<body>
    <a href="link.html">{link_name}</a>
    
    <!-- nume_block1_parsed -->
    
    Aici putem avea orice; tabele, imagini ...
    
    <!-- nume_block2_parsed -->
</body>
</html>'
;

$this->blocks['nume_block1'] = 'Aici vom scrie ceva care va intra intr-o bucla (loop) {vars_block1}';
$this->blocks['nume_block2'] = 'Aici vom scrie ceva care va intra intr-o bucla (loop) {vars_block2}';

Acum ne trebuie o functie care sa schimbe fiecare {variabila} din fiecare block cu o valoare si sa salveze fievare block intr-o alta variabila.
Dupa ce trecem functia intr-o bucla de 4 ori, $this->blocks[$block_name."_parsed"] va contine:

$this->blocks[$block_name."_parsed"] =
"Aici vom scrie ceva care va intra intr-o bucla (loop) variabila1
Aici vom scrie ceva care va intra intr-o bucla (loop) variabila2
Aici vom scrie ceva care va intra intr-o bucla (loop) variabila3
Aici vom scrie ceva care va intra intr-o bucla (loop) variabila4"
;

function parse($block_name)
{
    
$temp $this->blocks[$block_name];
    
// cu eregi_replace vom schimba fiecare variabila;
    
foreach($this->vars as $key => $value)
    {
        
// aici problema este atunci cand suntem intr-o bucla,
        // $this->blocks[$block_name] nu va mai contine nici o {variabila} pt ca am schimbato deja
        // din cauza asta am asignat o alta variabila mai sus $temp
        
$this->blocks[$block_name] = eregi_replace("{".$key."}"$value$this->blocks[$block_name]);
    }
    
// dupa ce toate schimbarile sunt facute vom salva blockul in $this->blocks[$block_name."_parsed"];
    
$this->blocks[$block_name."_parsed"] .= $this->$blocks[$block_name];
    
    
// si resetam $this->$blocks[$block_name] sa contina aceleasi date 
    // adica datele din fisierul original
    
$this->$blocks[$block_name] = $temp;
    
    
//cum nu mai avem nevoie de variabila temporala o eliminam
    
unset($temp);
}

Singurul lucru care nu merge bine in functia de mai sus este ca nu avem nici un array() care sa contina:

$array['nume_variabila'] = 'valuare cu care sa schimbam variabila';

Vom declara o noua variabila in aceasta clasa:

public $vars;
    
// ne trebuie o functie in care sa putem defini ce variabile trebuiesc inlocuite si cu ce valori
function set_var($var)
{
    foreach(
$var as $key => $value)
    {
        
$this->vars[$key] = $value;        
    }                
}

// functia de mai sus este destul de buna dar ne obliga sa introducem un array() cand o folosim
// Putem incerca cu "key", "valoare"
function set_var($var$value false)
{
    if(
is_array($var))
    {
        foreach(
$var as $key => $val)
        {
            
$this->vars[$key] = $val;
        }                
    }
    else
    {
        
$this->vars[$var] = $value;
    }
}

In prima linie declaram $value = false; pt ca este optional, daca $var este un array() atunci nu mai avem nevoie si de $value;

Pana acum am reusit sa salvam continutul paginii html intr-o variabila, sa scoatem blockurile, sa le modificam si sa le salvam intr-o noua variabila dar mai avem nevoie de o functie care sa rescrie blockurile in pagina:

function reBuildPage()
{
    
// nu avem nevoie de nici o variabila in functia asta pentru ca avem tot ce ne trebuie
    // avem pagina si locul unde intra fiecare block scris ca <!-- block_name_parsed -->
    // tot ce mai trebuie sa facem e sa scoatem fiecare "<!-- block_name_parsed -->" din pagina
    // si sa-l inlocuim cu valoarea din variabila $this->blocks[]
    
foreach($this-blocks as $key => $val)
    {
        
$this->file_contents eregi_replace("<!-- $key -->"$val$this->file_contents);
    }
}

Asta este tot ce trebuie sa facem ca sa reintroducem blockurile in pagina.

Acum ne mai trebuie functia __construct() sau template():

function __construct($file_name)
{
    
// aici initiem fiecare variabila
    
$this->vars   = array();
    
$this->blocks = array();
    
// pentru a seta si variabila $this->file_contents trebuie sa executam functia set_file();
    
$$this->set_file($file_name);
}

Dupa ce executam:

$tpl = new template('template.page.html');

Avem:

$tpl->vars = array();
$tpl->blocks = array();
$tpl->file_contents '
<html>
<head>
    <title>{titlu}</title>
</head>
<body>
    <a href="link.html">{link_name}</a>
    
    <!-- BEGIN BLOCK nume_block1 -->
        Aici vom scrie ceva care va intra intr-o bucla (loop) {vars_block1}
    <!-- END BLOCK nume_block1 -->

    Aici putem avea orice; tabele, imagini ...

    <!-- BEGIN BLOCK nume_block2 -->
        Aici vom scrie ceva care va intra intr-o alta bucla (loop) {vars_block2}
    <!-- END BLOCK nume_block2 -->
</body>
</html>'
;

// scoatem toate blockurile:
$tpl->get_blocks('nume_block1');
$tpl->get_blocks('nume_block2');

// acum avem:
$tpl->vars   = array();
$tpl->blocks = array('nume_block1' => 'Aici vom scrie ceva care va intra intr-o bucla (loop) {vars_block1}',
                     
'nume_block2' => 'Aici vom scrie ceva care va intra intr-o bucla (loop) {vars_block2}');
$tpl->file_contents '
<html>
<head>
    <title>{titlu}</title>
</head>

<body>
    <a href="link.html">{link_name}</a>
    
    <!-- nume_block1_parsed -->
    
    Aici putem avea orice; tabele, imagini ...
    
    <!-- nume_block2_parsed -->
</body>
</html>'
;

// pentru a folosi o bucla vom initia un array() cu alte 3 inauntru;
$vars_block1 = array(
            array(
'vars_block1' => 'Sunt in loop 1'),
            array(
'vars_block1' => 'Sunt in loop 2'),
            array(
'vars_block1' => 'Inca mai sunt in loop'));

// creem o bucla si setam de fiecare data variabila din blockul 1
for($i=0$i<count($vars_block1); $i++)
{
    
// setam de fiecare data variabila vars_block1
    
$tpl->set_var($vars_block1[$i]);
    
    
// si o schimbam de fiecare data
    
$tpl->parse('nume_block1');
}
                                                                                
// dupa for avem:
$this->blocks = array(
'nume_block1'        => 'Aici vom scrie ceva care va intra intr-o bucla (loop) {vars_block1}',

'nume_block2'        => 'Aici vom scrie ceva care va intra intr-o bucla (loop) {vars_block2}',

'nume_block1_parsed' => 'Aici vom scrie ceva care va intra intr-o bucla (loop) Sunt in loop 1
                         Aici vom scrie ceva care va intra intr-o bucla (loop) Sunt in loop 2
                         Aici vom scrie ceva care va intra intr-o bucla (loop) Inca mai sunt in loop'
);

// acelasi lucru il vom face si pentru blockul nume_block2
$vars_block2 = array(
            array(
'vars_block2' => 'sunt block2 - sunt in loop 1'),
            array(
'vars_block2' => 'sunt block2 - sunt in loop 2'),
            array(
'vars_block2' => 'sunt block2 - si inca in loop'));

for(
$i=0$i<count($vars_block2); $i++)
{
    
// setam de fiecare data variabila vars_block2
    
$tpl->set_var($vars_block2[$i]);
    
    
// si o schimbam de fiecare data
    
$tpl->parse('nume_block2');
}

// dupa for avem:
$this->blocks = array(
'nume_block1'        => 'Aici vom scrie ceva care va intra intr-o bucla (loop) {vars_block1}',

'nume_block2'        => 'Aici vom scrie ceva care va intra intr-o bucla (loop) {vars_block2}',

'nume_block1_parsed' => 'Aici vom scrie ceva care va intra intr-o bucla (loop) Sunt in loop 1
                         Aici vom scrie ceva care va intra intr-o bucla (loop) Sunt in loop 2
                         Aici vom scrie ceva care va intra intr-o bucla (loop) Inca mai sunt in loop'
,
                         
'nume_block2_parsed' => 'Aici vom scrie ceva care va intra intr-o bucla (loop) sunt block2 - sunt in loop 1
                         Aici vom scrie ceva care va intra intr-o bucla (loop) sunt block2 - sunt in loop 2
                         Aici vom scrie ceva care va intra intr-o bucla (loop) sunt block2 - si inca in loop'
);

Acum avem si blockurile si pagina pregatita executand:

$tpl->reBuildPage();

Obtinem:

$tpl->file_contents '
<html>
<head>
    <title>{titlu}</title>
</head>
<body>
    <a href="link.html">{link_name}</a>
    
    Aici vom scrie ceva care va intra intr-o bucla (loop) Sunt in loop 1
    Aici vom scrie ceva care va intra intr-o bucla (loop) Sunt in loop 2
    Aici vom scrie ceva care va intra intr-o bucla (loop) Inca mai sunt in loop
    
    Aici putem avea orice; tabele, imagini ...
    
    Aici vom scrie ceva care va intra intr-o bucla (loop) sunt block2 - sunt in loop 1
    Aici vom scrie ceva care va intra intr-o bucla (loop) sunt block2 - sunt in loop 2
    Aici vom scrie ceva care va intra intr-o bucla (loop) sunt block2 - si inca in loop
</body>
</html>'
;

Totul corect pana acum numai ca in pagina mai exista 2 variabile care nu le-am schimbat si anume {titlu} si {link_name}
Pentru asta trebuie sa setam inca 2 variabile si sa le schimbam:

$tpl->set_var("titlu""Titlul paginii mele!");
$tpl->set_var("link_name""Numele linkului meu!");

Acum avem setate si cele 2 variabile dar trebuie sa le schimbam, creem o noua functie:

function page_parse()
{
    foreach(
$this->vars as $key => $val)
    {
        
$this->file_contents eregi_replace("{".$key."}"$val$this->file_contents);        
    }
}

Dupa ce executam:

$tpl->page_parse();

Vom obtine pagina finala care arata cam asa:

$tpl->file_contents '
<html>
<head>
    <title>Titlul paginii mele!</title>
</head>

<body>
    <a href="link.html">Numele linkului meu!</a>
    
    Aici vom scrie ceva care va intra intr-o bucla (loop) Sunt in loop 1
    Aici vom scrie ceva care va intra intr-o bucla (loop) Sunt in loop 2
    Aici vom scrie ceva care va intra intr-o bucla (loop) Inca mai sunt in loop
    
    Aici putem avea orice; tabele, imagini ...
    
    Aici vom scrie ceva care va intra intr-o bucla (loop) sunt block2 - sunt in loop 1
    Aici vom scrie ceva care va intra intr-o bucla (loop) sunt block2 - sunt in loop 2
    Aici vom scrie ceva care va intra intr-o bucla (loop) sunt block2 - si inca in loop
</body>
</html>'
;

Acum singurul lucru este sa o trimitem catre browser:
Pentru asta definim o noua functie:

function display()
{
    print 
$this->file_contents;    
}


$tpl->display();

Dar daca ne uitam mai sus vedem cum trebuiesc executate 2 functii care se pot executa si in clasa pe care am creat-o si in loc de:

$tpl = new template('template.page.html');
$tpl->get_blocks('nume_block1');
$tpl->get_blocks('nume_block2');

// buclele pt fiecare block

$tpl->set_var("title""Titlul paginii mele!");
$tpl->set_var("link_name""Numele linkului meu!");

// urmatoarele 2 functii le putem executa in declaratia functiei display()
$tpl->reBuildPage();
$tpl->parse_page();
$tpl->display();

Rescriem functia display():

function display()
{
    
$this->reBuildPage();
    
$this->parse_page();
    print 
$this->file_contents;    
}

In felul asta scapam de 2 linii.
Este destul de bine asa clasa dar inca mai putem scapa de cateva linii si anume de:

$tpl->get_blocks('nume_block1');
$tpl->get_blocks('nume_block2');

Cum?
Executam functia cand creem o noua instanta a obiectului:

function __construct($file_name$blocks_names = array())
{
    
// aici initiem fiecare variabila
    
$this->vars = array();
    
$this->blocks = array();
    
// pt a seta si variabila $this->file_contents trebuie sa executam functia set_file();
    
$this->set_file($file_name);

    
// acum vom scoate blockurile aici:
    
foreach($blocks_names as $block)
    {
        
$this->get-blocks($block);
    }
}

Sa vedem cum trebuia sa executam inainte si dupa:

// ===== inainte ===== \\
$tpl = new template('template.page.html');
$tpl->get_blocks('nume_block1');
$tpl->get_blocks('nume_block2');
$tpl->set_var("title""Titlul paginii mele!");
$tpl->set_var("link_name""Numele linkului meu!");

for(
$i=0$i<count($vars_block1); $i++)
{
    
// setam de fiecare data variabila vars_block1
    
$tpl->set_var($vars_block1[$i]);
    
    
// si o schimbam de fiecare data
    
$tpl->parse('nume_block1');
}

for(
$i=0$i<count($vars_block2); $i++)
{
    
// setam de fiecare data variabila vars_block2
    
$tpl->set_var($vars_block2[$i]);
    
    
// si o schimbam de fiecare data
    
$tpl->parse('nume_block2');
}

$tpl->reBuildPage();
$tpl->parse_page();
$tpl->display();

// ===== dupa ===== \\
$tpl = new template('template.page.html', array('nume_block1''nume_block2'));
$tpl->set_var("title""Titlul paginii mele!");
$tpl->set_var("link_name""Numele linkului meu!");

for(
$i=0$i<count($vars_block1); $i++)
{
    
// setam de fiecare data variabila vars_block1
    
$tpl->set_var($vars_block1[$i]);
    
    
// si o schimbam de fiecare data
    
$tpl->parse('nume_block1');
}

for(
$i=0$i<count($vars_block2); $i++)
{
    
// setam de fiecare data variabila vars_block2
    
$tpl->set_var($vars_block2[$i]);
    
    
// si o schimbam de fiecare data
    
$tpl->parse('nume_block2');
}

$tpl->display();

Clasa template finala:

<?php
class template
{
    public 
$vars;
    public 
$blocks;
    public 
$file_contents;
    
    function 
__construct($file_name$blocks_names = array())
    {
        
$this->t;vars = array();
        
$this->t;blocks = array();
        
        
$this->set_file($file_name);
        
        foreach(
$blocks_names as $block)
        {
            
$this->get-blocks($block);
        }
    }
    
    function 
set_file($file_name)
    {
        
$this->file_contents implode(""file($file_name));
    }

    function 
get_blocks($block_name)
    {
        
$page explode("<!-- BEGIN BLOCK $block_name -->"$this->file_contents);
        
$this->file_contents $page[0]."<!-- {$block_name}_parsed -->";
        
$page explode("<!-- END BLOCK $block_name -->"$page[1]);
        
$this->file_contents.= $page[1];
        
$this->blocks[$block_name] = $page[0];
    }

    function 
parse($block_name)
    {
        
$temp $this->blocks[$block_name];
        foreach(
$this->vars as $key => $value)
        {
            
$this->blocks[$block_name] = eregi_replace("{".$key."}"$value$this->blocks[$block_name]);
        }
        
        
$this->blocks[$block_name."_parsed"] .= $this->$blocks[$block_name];
        
        
$this->$blocks[$block_name] = $temp;

        unset(
$temp);
    }

    function 
set_var($var$value false)
    {
        if(
is_array($var))
        {
            foreach(
$var as $key => $val)
            {
                
$this->vars[$key] = $val;        
            }                
        }
        else
        {
            
$this->vars[$var] = $value;        
        }
    }
    
    function 
reBuildPage()
    {
        foreach(
$this-blocks as $key => $val)
        {
            
$this->file_contents eregi_replace("<!-- $key -->"$val$this->file_contents);
        }
    }
    
    function 
page_parse()
    {
        foreach(
$this->vars as $key => $val)
        {
            
$this->file_contents eregi_replace("{".$key."}"$val$this->file_contents);        
        }                
    }
    
    function 
display()
    {
        
$this->reBuildPage();
        
$this->parse_page();
        print 
$this->file_contents;    
    }
}

?>

Asta este tot.

Cum se poate imbunatati?

Sper sa va foloseasca acest mic tutorial, pentru orice eroare/imbunatatire/multumiri trimite un e-mail la x_atrix AT yahoo DOT com