Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Klasa tpl, i parsowanie {SECTION} od smarty'iego
Forum PHP.pl > Forum > PHP
radziel
Napisałem sobie na własny użytek taką oto klase do obsługi szablonów (jako alternatywe dla Smarty, gdyż on baaaardzo opóźnia mój skrypt(tak bylo pod PHP4) i nie dziala pod PHP5 :/)

[php:1:7869633014]<?php
class template
{
var $parsed;
var $unparse;
var $blocks;

var $dir;

function __construct($dir)
{
$this->_setDir($dir);
}

function _setDir($dir)
{
if (is_dir($dir))
{
$this-> dir = $dir;
return true;
}
else
{
die("[TEMPLATE]Root dir no exists!");
}
}
function Assign($var, $value=null)
{
if(is_array($var))
{
reset($var);
foreach ($var as $name => $val)
{
$this -> blocks[$name] = $val;
}
}
else
{
$this -> blocks[$var] = $value;
}
}

function Display($file)
{
$this -> unparse = @file($dir . $file . '.tpl');
echo $this -> _parse();
}

function _parse()
{
$this -> parse = '';
for ($i=0; $i<= count($this->unparse); $i++)
{
$line = $this -> unparse[$i];
$found = array();

if(preg_match_all("#{(.+?)}#is", $line, $found))
{
foreach ($found[1] as $block)
{
$block_names[]='{'.$block.'}';
$block_values[] = $this -> blocks[$block];
}
$line = str_replace($block_names, $block_values, $line);
}

$this -> parsed .= $line;
}
unset($this->unparse);
return $this -> parsed;
}
function _parseSectionTag()
{
// e? co tu napisac?
}


}
?>[/php:1:7869633014]

Jak już pewnie niektórzy zauważyli jest to modyfikacja kodu ze strony Webcity.pl Dodalem pare rzeczy, usunełem niepotrzebne ale...
Mam problem ze znacznikiem {SECTION}{SECTION} uzywam go bardzo czesto więc musze napisać odpowiedni parser dla niego...

Kompletnie nie wiem jak za to się zabrać... Przykladowy tpl:
Kod
<table border="1">

  {section name=config_value loop=$data}

    <tr>

      <td>{$data[config_value].name}</td>

      <td>{$data[config_value].value}</td>

    </tr>

  {/section}

</table>


Składnia jest taka sama jak u smartiego...
Przeglądałem kod SMARTY'iego, ale nie mogę wyciągnąć funcji za to odpowiedzialnej... strasznie zakręcone to wszystko :/

Ma ktoś pomysł jak to rozwiązać? Niech rzuci kodem, albo niech da jakas wskazówke tongue.gif
Bora
kiedyś napisałem coś takiego:

[php:1:7d21b2379c]<?php
class template
{
var $file;
var $inc = array("default" => "");
var $blocks = array("default" => "");
var $moduls = array("default" => "");
function load($file){
$file = "pages/".$_SESSION['page']."/templates/".$file.".tpl";
if(file_exists($file)){
$plik = fopen($file, 'r');
$unparsed = fread($plik, filesize($file));
fclose($plik);
}else{
die("brak pliku $file");
}
// wylapuje moduły
preg_match_all( "#[INCLUDE:(.+?)]#is", $unparsed, $include);
$unparsed = preg_replace("#[INCLUDE:(.+?)]#is","{INCLUDE:$1}", $unparsed);
$unparsed = str_replace("n", "|ent|", $unparsed);
preg_match_all( '/[MODUL.*](.+)[/MODUL.*]/Uise', $unparsed, $znalezione);
// zamienia moduły na ich odpowiedniki
$unparsed =
preg_replace('/[MODUL:(.*?)](.*?)[/MODUL:(.*?)]/i','{MODUL:$1}',
$unparsed);
$unparsed = str_replace("|ent|", "n", $unparsed);
$znalezione[0] = str_replace("|ent|", "n", $znalezione[0]);
$znalezione[1] = str_replace("|ent|", "n", $znalezione[1]);
$mod = array();
foreach ($znalezione[0] as $i_parser){
preg_match("/[MODUL:(.*?)]/i",$i_parser, $znal);
$pref = $znal[1];
$m = preg_replace('/[MODUL:(.*?)]/i','', $i_parser);
$m = preg_replace('/[/MODUL:(.*?)]/i','', $m);
$mod["$pref"]=$m;
}
// wyłapuje include i wstawia pliki
foreach ($include[0] as $i_parser){
preg_match("/[INCLUDE:(.*?)]/i",$i_parser, $znal);
$in = preg_replace("#[INCLUDE:(.+?)]#is","$1", $i_parser);
$pref = $znal[1];
$prefix = $znal[1];
$pref = "templates/".$pref.".tpl";
if(file_exists($pref)){
$plik = fopen($pref, 'r');
$files = fread($plik, filesize($pref));
$unparsed = str_replace('{INCLUDE:'.$prefix.'}',$files, $unparsed);
fclose($plik);
}else{
die("brak pliku $pref");
}
}
$this -> moduls = $znalezione[1];
$this -> mods = $mod;
$this -> unparsed = $unparsed;
return true;
}
function parse($unparsed,$blocks = array()){
if(preg_match_all('#{(.+?)}#is', $unparsed, $found)){
$parsed = $unparsed;
foreach($found[1] as $block){
// var_dump($block);
// var_dump($blocks);
$parsed = str_replace('{'.$block.'}', $blocks[$block], $parsed);
}
}
return $parsed;
}
}
class modul
{
var $file;
var $mod;
var $blocks = array("default" => "");
var $moduls = array("default" => "");
function parse($unparsed,$blocks = array()){
if(preg_match_all('#{(.+?)}#is', $unparsed, $found)){
$parsed = $unparsed;
foreach($found[1] as $block){
$parsed = str_replace('{'.$block.'}', $blocks[$block], $parsed);
}
}
return $parsed;
}
}
?>[/php:1:7d21b2379c]

[xml:1:7d21b2379c]<!--- [MODUL:koment] dolna czesc-->
<tr>
<td class="forum1">
autor:{koment:autor} - {koment:kasuj} - data:{koment:data}
<br>
{koment:tresc}
<br>
{koment:ip} - {koment:host}
</td>
</tr>
<!--- [/MODUL:koment] dolna czesc-->[/xml:1:7d21b2379c]


może ci sie przyda

update to jest bardzo stary kod i juz nie pammiętam jak działał. ale patrząc w zródło stronki jest strasznie zawiłe.

* * * * * * * * * * * * * * * * * * *
Post nr: [100] smile.gif trza to oblać smile.gif
radziel
Hm... ciekawe...

Ma może ktoś jeszcze jakieś pomysły?
Bora
jesatem w trakcie pisana niedługo dam gotową klase
gulldarek
Bora: nie wiem czy widziałeś kod z vbulletina któy wkleiłem do mojego wątku o szablonach. Może się przydać smile.gif

Ps. Daj znać jak ją skończysz winksmiley.jpg
Bora
Napiałem radzi sobie narazie tylko z 1 subsekcją , próbowałem z zagnieżdżonymi ale narazie nie wychodzi.

[php:1:94a80b8b43]<?php
class template
{
var $parsed;
var $unparse;
var $blocks;
var $lines;

var $dir;

//function __construct($dir)
function template($dir)
{
$this->_setDir($dir);
}

function _setDir($dir)
{
if (is_dir($dir))
{
$this-> dir = $dir;
return true;
}
else
{
die("[TEMPLATE]Root dir no exists!");
}
}
function Assign($var, $value=null)
{
if (strstr($var, '.') )
{
$var = explode('.',$var);
for ($i=0;$i<count($value);++$i)
{
$this -> blocks[$var['0']][$i][$var['1']] = $value;
}
}else{
$this -> blocks[$var] = $value;
}
}

function Display($file)
{
$this -> unparse = file($dir . $file . '.tpl');
$fh = fopen($dir . $file . '.tpl', "r");
$this -> unparse = chop(fread($fh, filesize($dir . $file . '.tpl')));
$i=0;
while ( ereg( '{section name', $this->unparse) )
{
$this -> _parseTab();
++$i;
if ($i>6){exit('za dluga petla');}
}
$this -> unparse = $this->_parse($this -> unparse);
echo $this -> unparse ;
}

function _parseTab()
{
$line = $this -> unparse;
preg_match( '/{section name=(.+?)}(.*){/section}/is', $line, $found);
$line = preg_replace( '/{section name=(.*)}(.+){/section}/is',
$this->_parse_intab($found['2'],$this->blocks[$found['1']]['0'],$found['1'])
,$line);
$line = str_replace('{tmp}', '', $line);
$this->unparse = $line;
return false;
}


function _parse($line)
{
$found = array();

if(preg_match_all("#{(.+?)}#is", $line, $found))
{
foreach ($found['1'] as $block)
{
$block = str_replace('$', '', $block);
$block_names='{$'.$block.'}';
$block_values = $this -> blocks[$block];
$line = str_replace($block_names, $block_values, $line);
}
$line = str_replace($block_names, $block_values, $line);
}
return $line;
}

function _parse_intab($line,$val,$mod)
{

$found = array();
$count_var = count($val);
if(preg_match_all("#{[$]{$mod}[.](.+?)}#is", $line, $found))
{
foreach ($found['1'] as $block)
{
$block_mod = $block['0'];
$block_names='{$'.$mod.".".$block.'}';
$block_values = $this->blocks[$mod]['0'][$block]['0'];
if (!empty($lines))
{
$lines=explode('{tmp}',$lines);
for ($i=0;$i<$count_var;++$i)
{
$lines[$i] = str_replace($block_names, $block_values[$i], $lines[$i]);
}
$lines=implode('{tmp}',$lines);
}else{
for ($i=0;$i<$count_var;++$i)
{
$lines[$i] = str_replace($block_names,
$block_values[$i], $line);

}
$lines=implode('{tmp}',$lines);
}
}
}
return $lines;
}
}
?>[/php:1:94a80b8b43]


Kod
test Parsera - {$tpl}-

<table border="1">

  {section name=config_value}

    <tr>

      <td>[{$config_value.name}]</td>

      <td>[{$config_value.value}]</td>

    </tr>

  {/section}



</table>


[php:1:94a80b8b43]<?php
include('tpl_class.php');
$tpl= new template('.');
$tpl->Assign("config_value.id",array('aaa1i','bbbb2i','cccc3i'));
$tpl->Assign("config_value.name",array(array('aaa1n','bbbb2n','cccc3n')));
$tpl->Assign("config_value.value",array(array('aaa1v','bbbb2v','cccc3v')));
$tpl->Assign("config_test.name",array(array('configa1v','configb2v','configc3v')));
$tpl->Assign('tpl','templates');
$tpl = $tpl->Display('tpl');
?>[/php:1:94a80b8b43]

UPDATE

wersja poprawiona
gulldarek
Bora: teraz przydalaby sie eszcze funkcja do parsowania <if>'ow...
radziel
Bora: nieco musisz zmodyfikowac te parsowanie sectionów
Kod
<table border="1">

  {section name=config_value loop=$data}

    <tr>

      <td>{$data[config_value].name}</td>

      <td>{$data[config_value].value}</td>

    </tr>

  {/section}

</table>


powininieneś w assign podawać tylko assign($data), parser sam powinien podstawic (jezeli to tablica) odpowiednie wartości za $data[config_value].name i $data[config_value].value...

Te dane w tych kwadratowych nawiasach to info ze ta zmienna nalezy do sekcji config_value.

Przydałoby się jeszcze aby parsował loop i tyle razy powtarzał ten kod ile ma $data tych "indexów" w sobie.. to by oszczedziło nieco czasu przy zmianie klas ze smarty na tą...

Sorry ze tak pisze jak dla lamera, ale chce zeby tez poczatkujacy to zrozumieli smile.gif

Czekam az beda dzialac zagnieżdzone sectiony winksmiley.jpg Dobrze sie zapowiada smile.gif
Bora
teraz męcze sie z wyrażniem regularnym , które mnie przerasta

mam coś takiego:
Kod
{section name=config_value}

    <tr>

      <td>[{$config_value.name}]</td>

      <td>[{$config_value.value}]</td>

    </tr>

    {section name=config_test}[[{$config_test.name}]]{/section}

  {/section}

licze ilosc otwartych subsekcji
[php:1:17fb8f4b41]<?php
substr_count($found['0'], '{section name');
?>[/php:1:17fb8f4b41]
i teraz zaczyna sei jazda , chce wyciągnąć z tego stringa który kończyłby sie po zamknięciu ostatniej otwartej subsekcji czyli w tym przypadku po 2gim
Kod
{/section}


UPDATE
powyższy kod poprawiony[/code]
Bora
Tak jak chciałęś radziel Assign jak w smarty co do sposobu czytania z tpl zostawiam to na pozniej jak juz bede miał gotowe wyrażenie.


[php:1:a29cc6a01f]<?php
include('tpl_class.php');
$tpl= new template('.');
$tpl->Assign("config_test",array(array('configa1v','configb2v','configc3v')));
$tpl->Assign("config_value",array('name'=>array('aaa1n','bbbb2n','cccc3n'),'value'=>array('aaa1v','bbbb2v','cccc3v')));
$tpl->Assign('tpl','templates');
$tpl = $tpl->Display('tpl');
?>[/php:1:a29cc6a01f]

Kod
test Parsera - {$tpl}-

<table border="1">

  {section name=config_value}

    <tr>

      <td>[{$config_value.name}]</td>

      <td>[{$config_value.value}]</td>

    </tr>



  {/section}

</table>



[php:1:a29cc6a01f]<?php
class template
{
var $parsed;
var $unparse;
var $blocks;

var $dir;

//function __construct($dir)
function template($dir)
{
$this->_setDir($dir);
}

function _setDir($dir)
{
if (is_dir($dir))
{
$this-> dir = $dir;
return true;
}
else
{
die("[TEMPLATE]Root dir no exists!");
}
}
function Assign($var, $value=null)
{
if (is_array($value))
{
$wymiar=count($value);
if ($wymiar==1)
{
foreach ($value as $val)
{
$this -> blocks[$var] = $val;
}
}else{
$klucze = array_keys($value);
foreach ($klucze as $klucz)
{
foreach ($value[$klucz] as $val)
{
$this -> blocks[$var][$klucz][] = $val;
}
}
}
}else{
$this -> blocks[$var] = $value;
}
}

function Display($file)
{
$this -> unparse = file($dir . $file . '.tpl');
$fh = fopen($dir . $file . '.tpl', "r");
$this -> unparse = chop(fread($fh, filesize($dir . $file . '.tpl')));
$i=0;
while ( ereg( '{section name', $this->unparse) )
{
$this -> _parseTab();
++$i;
if ($i>6){exit('za dluga petla');}
}
$this -> unparse = $this->_parse($this -> unparse);
echo $this -> unparse ;
}

function _parseTab()
{
$line = $this -> unparse;
preg_match( '/{section name=(.+?)}(.*){/section}/is', $line, $found);
$line = preg_replace( '/{section name=(.*)}(.+){/section}/is', $this->_parse_intab($found['2'],$this->blocks[$found['1']]['0'],$found['1']),$line);
$line = str_replace('{tmp}', '', $line);
$this->unparse = $line;
return false;
}


function _parse($line)
{
$found = array();

if(preg_match_all("#{(.+?)}#is", $line, $found))
{
foreach ($found['1'] as $block)
{
$block = str_replace('$', '', $block);
$block_names='{$'.$block.'}';
$block_values = $this -> blocks[$block];
$line = str_replace($block_names, $block_values, $line);
}
$line = str_replace($block_names, $block_values, $line);
}
return $line;
}

function _parse_intab($line,$val,$mod)
{

$found = array();

if(preg_match_all("#{[$]{$mod}[.](.+?)}#is", $line, $found))
{
foreach ($found['1'] as $block)
{
$block_names='{$'.$mod.".".$block.'}';
$block_values = $this->blocks[$mod][$block];
$count_var = count($this->blocks[$mod][$block]);
if (!empty($lines))
{
$lines=explode('{tmp}',$lines);
for ($i=0;$i<$count_var;++$i)
{
$lines[$i] = str_replace($block_names, $block_values[$i], $lines[$i]);
}
$lines=implode('{tmp}',$lines);
}else{
for ($i=0;$i<$count_var;++$i)
{
$lines[$i] = str_replace($block_names, $block_values[$i], $line);

}
$lines=implode('{tmp}',$lines);
}
}
}
return $lines;
}
}

?>[/php:1:a29cc6a01f]
radziel
Jako że temat dotyczy powyższego, postanowiłem napisać w tymże temacie winksmiley.jpg

Problem:
Powiedzmy dostaję zmienną o wartości "{$data[testowa].name}" a chce przekształcić ten string na "$data['name']" wie ktoś jak to zrobic? Nie mogę wyrazenia ułożyć - to moja słaba strona sad.gif
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.