سلام دوستان،
چند تا از دوستان خواسته بودن در مورد طرض کار و استفاده از کلاس Template توضيحاتي بدم. که البته توي اين پست فقط در مورد طرض استفادش توضيح مي دم.
اول کد کلاس رو ببينيد:
اين کلاس رو از يه Counter آلماني کپي زدم.
- کد: انتخاب همه
<?php
class Template
{
var $tags = array();
var $required_tags = array();
var $blocks = array();
var $tpl = '';
var $parsed_tpl = '';
function Template( $templatefile = '' )
{
if( !empty( $templatefile ) )
{
if( !file_exists( $templatefile ) )
{
print 'Could not find the template file <i>'. $templatefile ."</i>!\n";
return FALSE;
}
$this->load_file( $templatefile );
}
return TRUE;
}
/*-----------------------------------------------------------------*/
function load_template( $template )
{
$this->tpl .= $template;
}
/*-----------------------------------------------------------------*/
function load_file( $file )
{
if( empty( $file ) )
{
return FALSE;
}
$template = @implode( '', @file( $file ) );
if( $template == FALSE )
{
print 'Could not read the template file!';
return FALSE;
}
$this->tpl .= $template;
}
/*-----------------------------------------------------------------*/
function assign( $input, $value = '', $required = FALSE )
{
if( is_array( $input ) )
{
foreach( $input as $tag => $value )
{
if(empty( $tag ) )
{
print 'Tag name ist empty!';
return FALSE;
}
if( $required == TRUE )
{
$this->required_tags[$tag] = $value;
}
else
{
$this->tags[$tag] = $value;
}
}
}
elseif( is_string( $input ) )
{
if( empty( $input ) )
{
print 'Tag name ist empty!';
return FALSE;
}
else
{
if( $required == TRUE )
{
$this->required_tags[$input] = $value;
}
else
{
$this->tags[$input] = $value;
}
}
}
else
{
return FALSE;
}
return TRUE;
}
/*-----------------------------------------------------------------*/
function add_block($block_name, $block_array)
{
if( !is_string($block_name) || empty($block_name))
{
print 'Block name is not a string or is empty!';
return FALSE;
}
if( !is_array($block_array))
{
print 'Block array is not an array!';
return FALSE;
}
$this->blocks[$block_name][] = $block_array;
}
/*-----------------------------------------------------------------*/
function parse()
{
if( empty( $this->tpl ) )
{
return;
}
# blocks
$tmp_blocknames = array();
foreach( $this->blocks as $block_name => $block_arrays )
{
if( $anzahl = preg_match_all( '/<!-- BEGIN BLOCK '. preg_quote( $block_name, '/' ) .' -->(.*)<!-- END BLOCK '. preg_quote( $block_name, '/' ) .' -->/sU', $this->tpl, $matches ) )
{
for( $i = 0; $i < $anzahl; $i++ )
{
$block_plus_definition = $matches[0][$i];
$block = $matches[1][$i];
if( is_int( strpos( $block, '<!-- IF' ) ) )
{
$parse_control_structures = TRUE;
}
$parsed_block = '';
foreach( $block_arrays as $block_array )
{
$tmp = $block;
if( isset( $parse_control_structures ) )
{
$tmp = $this->_parse_control_structures( $tmp, array_merge( $block_array, $this->tags, $this->required_tags ) );
}
foreach( $block_array as $tag_name => $tag_value )
{
$tmp = str_replace( '{'.$tag_name.'}', $tag_value, $tmp );
}
$parsed_block .= $tmp;
}
$this->tpl = str_replace( $block_plus_definition, $parsed_block, $this->tpl );
$tmp_blocknames[] = $block_name;
unset( $parse_control_structures );
}
}
}
if( count( $this->blocks ) > 0 )
{
$this->tpl = preg_replace( "/<!-- (BEGIN|END) BLOCK (". implode( '|', $tmp_blocknames ) .") -->/", '', $this->tpl );
}
# unbenutze blِcke entfernen
$this->tpl = preg_replace( "/<!-- BEGIN BLOCK ([a-zA-Z0-9_-]+) -->.*<!-- END BLOCK \\1 -->(\r\n|\r|\n)?/msU", '', $this->tpl );
# single tags
foreach( $this->required_tags as $tag_name => $tag_value )
{
if( !is_int( strpos( $this->tpl, $tag_name ) ) )
{
print 'Could not find tag <i>'.$tag_name.'</i> in the template file!';
return FALSE;
}
else
{
$this->tpl = str_replace( '{'.$tag_name.'}', $tag_value, $this->tpl );
}
}
foreach( $this->tags as $tag_name => $tag_value )
{
$this->tpl = str_replace( '{'.$tag_name.'}', $tag_value, $this->tpl );
}
# if & else
$this->tpl = $this->_parse_control_structures(
$this->tpl,
array_merge( $this->tags, $this->required_tags ),
$this->blocks
);
$this->parsed_tpl = $this->tpl;
$this->tpl = '';
}
/*-----------------------------------------------------------------*/
function print_template()
{
if( !empty( $this->tpl ) )
{
$this->parse();
}
print $this->parsed_tpl;
}
/*-----------------------------------------------------------------*/
function get_tpl_as_var()
{
if( !empty( $this->tpl ) )
{
$this->parse();
}
return $this->parsed_tpl;
}
/*-----------------------------------------------------------------*/
function free()
{
$this->tpl = '';
$this->parsed_tpl = '';
$this->tags = array();
$this->required_tags = array();
$this->blocks = array();
}
/*-----------------------------------------------------------------*/
function _parse_control_structures( $tpl, $vars, $blocks = array() )
{
if( $matchnumber = preg_match_all( '/<!-- IF (!?)((BLOCK )?)([_a-zA-Z0-9\-]+) -->(.*)((<!-- ELSEIF !\(\\1\\2\\4\) -->)(.*))?<!-- ENDIF \\1\\2\\4 -->/msU', $tpl, $matches ) )
{
for( $i = 0; $i < $matchnumber; $i++ )
{
//print( $matches[8 ][$i] . '<br />');
if( !empty( $matches[2][$i] ) )
{
$code = 'if( '.$matches[1][$i].'isset($blocks[\''.$matches[4][$i].'\']) )'."\n";
}
else
{
$code = 'if( '.$matches[1][$i].'( isset($vars[\''.$matches[4][$i].'\']) ) )'."\n";
}
$code .= '{ $tpl = str_replace( $matches[0][$i], $this->_parse_control_structures( $matches[5][$i], $vars, $blocks ), $tpl ); }'."\n";
$code .= ' else '."\n";
$code .= '{ $tpl = str_replace( $matches[0][$i], !empty($matches[7][$i]) ? $this->_parse_control_structures( $matches[8][$i], $vars, $blocks ) : \'\', $tpl ); }';
eval( $code );
}
}
return $tpl;
}
}
?>
خوب اول طرض استفادش:
براي اين کار يه مثال ميزنم
فرض کنيد کد بالا رو توي يه فايل به نام Template.php ذخيره کرديم و يه فايل به نام index.php داريم که برنامه اصليمون هست و يه Folder به نام Tpls داريم که تمامي قالب هامون توي اونه، فعلا يه قالب به نام body.html داريم.
گام اول- محتويات فابل index.php :
- کد: انتخاب همه
<?php
include('Template.php');
$MyTpl = new Template();
$MyTpl -> load_file( 'Tpls/body.html' );
$MyTpl -> print_template();
?>
و محتواي body.html:
- کد: انتخاب همه
<html>
<head></head>
<body>
<p align="left">
Name:
<font color="#0000FF">
<b>
Ahmad
</b>
</font>
</p>
</body>
</html>
توضيح گام اول:
در کل يه فايل template رو باز مي کنيم و اونو نمايش مي ديم.
body.html که يه صفحه ساده HTML هست.
توي index.php خط اول که فايل حاوي کلاس Template رو include کرديم.
خط بعد يه Object جديد از اين کلاس رو تعريف کرديم با نام MyTpl :
- کد: انتخاب همه
$MyTpl = new Template();
خط بعد فايل قالب رو Load کرديم:
- کد: انتخاب همه
$MyTpl -> load_file( 'Tpls/body.html' );
دقت کنيد که نام و پسوند فايل قالب اصلا مهم نيست چي باشه. من براي راحتي پسوندش رو HTML گرفتم.
خط بعد کل قالب رو چاپ کرديم:
- کد: انتخاب همه
$MyTpl -> print_template();
خوب اين از گام اول بريم سراغ گام بعد...
ما قالب ها رو مي سازيم که کد HTML رو از کد PHP جدا کنيم و کارمون تميزتر باشه. ولي بايد بتونيم توي قالب تغييرات ايجاد کنيم.
توي اين کلاس چيزهايي که توي کد HTML مربوط به قالب با داده هاي توليد شده در کد PHP جايگزين مي شوند بين {} قرار مي گيرند. مثل قالب وبلاگ ها که چيزايي مثل اين دارند <**> ، <##> ، [] , ...
مثال:
محتويات body.html:
- کد: انتخاب همه
<html>
<head></head>
<body>
<p align="left">
Name:
<font color="#0000FF">
<b>
{TheVarName}
</b>
</font>
</p>
</body>
</html>
در اينجا TheVarName که در ميان {} قرار گرفته است در کد php با داده توليد شده جايگزين مي شه. توجه کنيد که اين کلاس به حروف بزرگ و کوچک حساس است.
کد index.php:
- کد: انتخاب همه
<?php
include('Template.php');
$MyTpl = new Template();
$MyTpl -> load_file( 'Tpls/body.html' );
if( 1 > 2 )
{
$Name = 'Ahamad';
} else {
$Name = 'Mohsen';
}
$MyTpl -> assign( 'TheVarName' , $Name );
$MyTpl -> print_template();
?>
خوب همون طور که مي بينيد يه خط جديد داريم:
- کد: انتخاب همه
$MyTpl -> assign( 'TheVarName' , $Name );
با صدا زدن اين Method توي قالب Load شده هر جا که {TheVarName} ديد اون رو با محتويات متغير Name جايگزين مي کنه.
اگه چند تا متغير داشتيم مي تونيم اين Method رو چند بار Call کنيم ولي يه راه ساده تر هم هست و اون اينه که ورودي آرايه بهش بديم اين طوري:
محتويات body.html:
- کد: انتخاب همه
<html>
<head></head>
<body>
<p align="left">
First name:
<font color="#0000FF">
<b>
{FrstName}
</b>
</font>
</p>
<p align="left">
Last name:
<font color="#0000FF">
<b>
{LstName}
</b>
</font>
</p>
</body>
</html>
محتويات index.php:
- کد: انتخاب همه
<?php
include('Template.php');
$MyTpl = new Template();
$MyTpl -> load_file( 'Tpls/body.html' );
$FName = 'Maryam';
$LName = 'Hamedi';
$NamesArray = array( 'FrstName' => $FName, 'LstName' => $LName);
$MyTpl -> assign( $NamesArray );
$MyTpl -> print_template();
?>
معمولا براي راحتي آرايه رو مستقيما توي ورودي Method تعريف مي کنيم و به يه شکل تميز تر مي نويسيم. براي اين که توي متغير هاي زياد قاطي نکنيم يعني اين طوري:
- کد: انتخاب همه
$FName = 'Maryam';
$LName = 'Hamedi';
$MyTpl -> assign( array(
'FrstName' => $FName,
'LstName' => $LName
)
);
//End of assign template vars -->
گام بعد- IF در قالب.
بعضي وقتا مي خواييم با توجه به شرايطي قسمت هايي از قالبتون نمايش داده نشه. مثال:
کد قالب:
- کد: انتخاب همه
<html>
<head></head>
<body>
<p align="left">
First name:
<font color="#0000FF">
<b>
{FrstName}
</b>
</font>
</p>
<!-- IF LstNameCond -->
<p align="left">
Last name:
<font color="#0000FF">
<b>
{LstName}
</b>
</font>
</p>
<!-- ENDIF LstNameCond -->
</body>
</html>
توي کد قالب به <!-- IF LstNameCond --> و <!-- ENDIF LstNameCond --> دقت کنيد که يک شرط رو بيان مي کنند LstNameCond عنوان دلخواهي براي شرط هست. خوب کد php:
- کد: انتخاب همه
$MyTpl -> assign( array(
'FrstName' => $FName,
'LstName' => $LName,
'LstNameCond' => 1
)
);
//End of assign template vars -->
طبق شرط بالا محتويات ميان IF نمايش داده مي شوند. توجه کنيد که به جاي عدد 1 هرچيز ديگري مي تواند باشد حتي 0 يا false، اما براي عدم نمايش کافيه که توي ليست assign نباشه. مثل اين:
- کد: انتخاب همه
$MyTpl -> assign( array(
'FrstName' => $FName,
'LstName' => $LName,
//'LstNameCond' => 1
)
);
//End of assign template vars -->
گام بعد- تکرار کد HTML.
فک کنم مهمترين قسمت اينجا باشه که ما مي خواهيم يه تعداد داده رو با قالب يکسان زير هم چاپ کنيم. براي اين کار به کد زير توجه کنيد:
کد قالب:
- کد: انتخاب همه
<html>
<head></head>
<body>
<p align="left">
#-
Name
</p>
<!-- BEGIN BLOCK MyBlock -->
<p align="left">
{Row}-
<b>
{Name}
</b>
</p>
<!-- END BLOCK MyBlock -->
</body>
</html>
توي اين کد هم دوقسمت به نام هاي <!-- BEGIN BLOCK MyBlock --> و <!-- END BLOCK MyBlock --> به چشم مي خوره ... هر چي بين اين دو Tag باشه تکرار مي شه مثل وبلاگ ها که براي نمايش پست ها معمولا اسم خود سرويس دهنده وبلاگ رو مي ذارن. MyBlock نام اين قسمت هست که دلخواهه.
کد php:
- کد: انتخاب همه
<?php
include('Template.php');
$MyTpl = new Template();
$MyTpl -> load_file( 'Tpls/body.html' );
$Names = array( 'Ali', 'Morteza', 'Javad' , 'Maryam', 'Ehsan' , 'Fatemeh' , 'Ahmad');
$TotalRecords = count( $Names);
for( $Index = 0 ; $Index != $TotalRecords ; $Index++ )
{
$MyTpl -> add_block('MyBlock', array(
'Row' => $Index + 1,
'Name' => $Names[ $Index ],
)
);
//End of assign template vars -->
}
$MyTpl -> print_template();
?>
براي اين که پيچيده نشه پاي DataBase رو وسط نکشيدم. فرض کنيد داده هاي ما توي آرايه Names هست و تعداد Record هامون هم توي TotalRecords هست. به ازاي هر تکرار داده بايد متد add_block رو صدا بزنيم و همين طور که مي بينيد داده ها رو بهش اختصاص بديم.
نکات قابل توجه:
1- ما ميتونيم مستقيما کدهاي HTML توليد شده رو چاپ نکنيم ... مثلا شايد بخواييم براي خبرناممون يه قالب داشته باشيم و اين رو بايد Mail کنيم. براي اين کار يه Method ديگه وجود داره که محتواي توليد شده رو بر مي گردونه:
- کد: انتخاب همه
$HtmlCode = $MyTpl -> get_tpl_as_var();
2- ما به هر تعداد که بخواييم مي تونيم قالب Load کنيم. يعني متد load_file رو مي تونيم به هر تعداد براي قالب هاي مختلف Call کنيم، تمام قالب ها مثل رشته اي پشت سر هم قرار مي گيرند.
کاربرد: براي جاهايي استفاده مي شه که مثلا شما يه Header و Footer ثابت داريد و فقط قسمت وسط صفحه عوض مي شه، مثل همين صفحه انجمن. مثال:
- کد: انتخاب همه
<?php
include('Template.php');
$MyTpl = new Template();
$MyTpl -> load_file( 'Tpls/Header.html' );
...
switch ( $Action)
{
case 'Login': $Page = 'Login.html'; break;
case 'Logout': $Page = 'Logout.html'; break;
case 'Contacts': $Page = 'Contacts.html'; break;
case 'ContactsSent': $Page = 'ContactsSent.html'; break;
default $Page = 'Index.html';
}
$MyTpl -> load_file( 'Tpls/' . $Page ); //Load the Body of page
...
$MyTpl -> load_file( 'Tpls/Footer.html' );
$MyTpl -> print_template();
?>
فقط توي اين قسمت بايد دقت کنيد که چون اين صفحات پشت سر هم مي آيند توي کد هاي HTML قاطي نشه که از تگ هاي HTML, Head , Body و ... هر کدوم 3 تا وجود داشته باشه.
خوب دوستان عزيز، من ديگه برم بخوابم.
اگه جاييش خوب توضيح داده نشده، بگيد تا بهتر توضيح بدم.
از اين که دير شد از همتون عذر مي خوام، ان شاء ا... بتونم بيشتر فعال باشم.
با آرزوي موفقيت و سربلندي براي تمامي عزيزان.
