天天看點

php smarty模闆引擎

<?php
/*
一、什麼是smarty?

smarty是一個使用PHP寫出來的模闆PHP模闆引擎,它提供了邏輯與外在内容的分離,簡單的講,
目的就是要使用PHP程式員同美工分離,使用的程式員改變程式的邏輯内容不會影響到美工的頁面設計,美工重新修改頁面不會影響到程式的程式邏輯,這在多人合作的項目中顯的尤為重要。

二、smarty優點:

1. 速度:采用smarty編寫的程式可以獲得最大速度的提高,這一點是相對于其它的模闆引擎技術而言的。

2. 編譯型:采用smarty編寫的程式在運作時要編譯成一個非模闆技術的PHP檔案,這個檔案采用了PHP與HTML混合的方式,在下一次通路模闆時将WEB請求直接轉換到這個檔案中,而不再進行模闆重新編譯(在源程式沒有改動的情況下)

3. 緩存技術:smarty選用的一種緩存技術,它可以将使用者最終看到的HTML檔案緩存成一個靜态的HTML頁,當設定smarty的cache屬性為true時,在smarty設定的cachetime期内将使用者的WEB請求直接轉換到這個靜态的HTML檔案中來,這相當于調用一個靜态的HTML檔案。

4. 插件技術:smarty可以自定義插件。插件實際就是一些自定義的函數。

5. 模闆中可以使用if/elseif/else/endif。在模闆檔案使用判斷語句可以非常友善的對模闆進行格式重排。

三、不适合使用smarty的地方:

1. 需要實時更新的内容。例如像股票顯示,它需要經常對資料進行更新,這類型的程式使用smarty會使模闆處理速度變慢。

2. 小項目。小項目因為項目簡單而美工與程式員兼于一人的項目,使用smarty會喪失php開發迅速的優點。


四、smarty目錄結構及版本
打開smarty的官方網站,www.smarty.net/download.php。下載下傳Smarty 3.1.12。有tar.gz和zip分别适用于linux和windows版本。

下載下傳好後Smarty-stable-3.1.12解壓縮會得到一個 Smarty-3.1.12 檔案夾,裡面有兩個主要檔案夾demo和libs

demo檔案夾為示例檔案夾,裡面包含預設檔案夾結構,是我們要進行編寫程式代碼的主要檔案夾。demo裡檔案夾的名稱都是smarty預設的目錄結構名稱,可以通過改smarty對應屬性值,再把檔案夾名改成我們想要的名稱。
libs為smarty代碼源檔案夾,一般不動。

/libs/Smarty.class.php   #主檔案

/libs/sysplugins/  #内部plugin

/libs /plugins/   #外部plugin,可自由擴充

/demo/cahce/   #放置緩存檔案

/demo/configs /   #放置可以載入的配置檔案

/demo/templates/   #放置模闆檔案

/demo/templates_c/    #放置對模闆編譯後的檔案

可以把解壓得到的 Smarty-3.1.12 檔案夾名改成我們想要的項目名,demo也可以改成我們想要的具體存放編碼的檔案夾的名稱

2、調試Smarty-3.1.12

建立自己的檔案,在demo檔案夾下建立index.php。
在templates目錄中建立模闆index.tpl
(幾乎可以是任何文本檔案的擴充名,常用的是tpl,php,html,不建議使用後兩者,因為可以從浏覽器直接通路而不安全。可以對apache的httpd.conf進行設定,禁止直接通路.tpl檔案。或者将templats目錄放在網站文檔樹之外。)

*/

//index.php代碼
require('../libs/Smarty.class.php');
$smarty = new Smarty;
//在調用的模闆裡可以通過{$name}來輸出name的值zhang,{}為這裡的smarty分界符
$smarty->assign('name','zhang');
//調用模闆tpl檔案裡不能執行PHP語句塊
$smarty->display('templates/index.tpl');


/*
index.tpl頁面内容

<html>
<body>

<span>你好, {$name}</span>

</body>
</html>
*/



/*
Smarty編譯時的處理過程是源php檔案->模闆檔案(可能調用多個或多次)->源php檔案。。。
也就是說不影響原php檔案的其他處理和輸出。是以smarty模闆檔案可以是完整的html,也可以是其中一部分。

smarty處理過程
smarty将php源檔案,首先編譯成中間檔案(也是php),如果啟用緩存,再根據編譯檔案生成緩存檔案(也是php),需要緩存的部分全部是寫死。
之後的每次通路都會通路編譯檔案(如果編譯檔案已經存在),一次編譯多次調用(可以是單檔案的多次,也可以是多檔案的多次),如果啟用緩存且有緩存檔案而且沒有過期,則直接通路緩存檔案,跳過編譯檔案。
編譯檔案一經生成,就不會被自動更新,除非模闆檔案或者配置檔案更改。源php檔案修改是不會引發重新編譯的。一旦編譯檔案重新生成,緩存檔案也必然重新生成。
*/

//Smarty允許有兩種特殊的編譯設定存在:
//1、 任何時候都不自動重新編譯(上線階段):隻有沒有該檔案的編譯檔案時才生成,模闆檔案或者配置檔案的更改,不會引發重新編譯。
$smarty->setCompile_check(false);//預設為true,false表示任何時候都不在檔案發生變更的情況下生成編譯檔案,除了無編譯檔案。
$smarty->getCompile_check();//獲得目前編譯檢查的設定
//2、任何時候都重新編譯(調試階段):任何時候都重新編譯。
$smarty->setForce_compile(true);//預設為false,true表示每次都重新編譯(啟用緩存的話,每次都重新緩存)
$smarty->getForce_compile();//獲得目前強制編譯的設定

//開啟緩存
$smarty->setCaching(true);
$smarty->getCaching();//擷取目前緩存狀态,預設是false關閉的
$smarty->setcache_lifetime(60);//設定緩存時間機關秒
//{*模版檔案*}
//{nocache}
//{$name}
//{/nocache}
//{*如果開啟緩存的話放在nocache标簽内的變量不會緩存,每次讀取PHP源檔案的值*}


/*
smarty分界符
在模闆檔案中,區分普通html代碼和smarty代碼靠的是分界符。預設是 {} ,但可能會與js和css相沖突。可以進行變更。
在3.0中模闆标簽将不支援空格,如{ $abc }在Smarty2中可以識别的,但是3.0裡頭就不行了,必須這樣{$abc},這樣是為了能夠更好的支援javascript和css。
*/
$smarty->left_delimiter = "{";   //左分界符,2.0屬性,3.0沿用
$smarty->right_delimiter = "}";
/*
分界符就相當于PHP的echo,分界符中的值都将輸出,除非指派等操作
smarty tpl檔案中分界符中兩個**之間的内容為注釋内容如
tpl檔案:
{*這是模闆注釋内容*}
*/


//設定緩存目錄路徑,不設預設"cache"
$smarty->setCacheDir("cache");
//擷取緩存目錄路徑
$smarty->getCacheDir();

//設定配置目錄路徑,不設預設"configs"
$smarty->setConfigDir("configs");
//添加配置目錄路徑,所有路徑将會以數組形式儲存,調用檔案時将在所有路徑中查找
$smarty->addConfigDir("configs/test");
//擷取配置目錄路徑的數組
$smarty->getConfigDir();

//設定插件目錄路徑,不設預設"plugins"
$smarty->setPluginsDir("plugins");
//添加插件目錄路徑,所有路徑将會以數組形式儲存,調用檔案時将在所有路徑中查找,plugins檔案夾裡放的就是可以在前台或背景按不同規則調用的函數的存儲檔案,檔案名及函數名的命名按不同調用規則有不同寫法要求
$smarty->addPluginsDir("plugins/test");
//擷取插件目錄路徑的數組
$smarty->getPluginsDir();

//設定模闆目錄路徑,不設預設"templates"
$smarty->setTemplateDir("templates");
//添加模闆目錄路徑,所有路徑将會以數組形式儲存,調用檔案時将在所有路徑中查找
$smarty->addTemplateDir("templates/test");
//擷取模闆目錄路徑的數組
$smarty->getTemplateDir();

//設定編譯目錄路徑,不設預設"templates_c"
$smarty->setCompileDir("templates_c");
//擷取編譯目錄路徑
$smarty->getCompileDir();
/*
我們可以建不同的php源檔案檔案夾,把編寫的php檔案按一定的分類放在不同的檔案夾中。
然後在每個檔案夾中都建立一個自定義的config檔案,在config檔案中建立一個新的$smarty = new Smarty 對象
然後把所有不同的檔案夾的php檔案的緩存,配置檔案,插件,模版,編譯目錄都設定到同一個緩存,配置檔案,插件,模版,編譯目錄
讓該檔案夾下所有PHP源檔案都引用該配置檔案即可擷取相同配置
*/


//模版變量
$arr = array(array("zhang","li"),'a'=>array("liu","wang"),array("ming","yi"));
$smarty->assign("testArr", $arr);
//設定模版變量,為将要調用的模版提供變量,在接下來調用的模版中可以通過{$testArr}或者{$testArr['a'][0]}或者{$testArr.a.0}來通路具體某數組元素
//在模版中可以直接通過 {$testArr = "testValue" scope="global"} 來更改傳過來的模闆變量的值(如果不存在則在模闆中建立并設定該模版變量),scope屬性是标注模闆變量使用範圍的可不寫
//在模版中更改或建立成其他數組 {$testArr = [1,2,3]}也可以{$testArr = [1,'a'=>2,2=>3]}也可以{$testArr[] = 4}或其他類似PHP中建立數組方式
//php源檔案可通過 $smarty->getTemplateVars("testArr") 擷取指定模版變量,如要擷取模闆中改變或建立的模版變量,在模闆中建立或更改其值時必須加上scope屬性并把值設定為scope="global"或scope="parent"

class A{
    function aa($nam){
        echo $nam;
    }
}
$smarty->assign("obj", new A);
//設定的模版變量是對象時在模版頁可以如下這樣調用,給模版傳類對象時也是傳址
//{$obj->aa('my name is y')}

//Smarty可以識别嵌入在雙引号中的模版變量,隻要此變量隻包含數字、字母、下劃線。但貌似隻支援能直接轉換成字元串的模版變量
$smarty->assign("testStr", "this is testStr");
//模闆中可通過{"$testStr OK !"}來通路



/*
tpl模闆包含模闆
模闆檔案:
{include file="header.tpl"}
header.tpl内容:
<span>這是頂部内容!!,歡迎你,{$name}</span>

模闆包含模闆也可以是這樣格式
{include file="header.tpl" testVar="這是頂部内容!!!"}
header.tpl則可以通過{$testVar}使用調用頁包含時傳來的模闆變量
header.tpl内容:
<span>{$testVar},歡迎你,{$name}</span><hr />
*/



/*
可以預先規定一系列的變量與值的對應,并放在配置檔案中,在使用時載入。
配置檔案預設放在configs檔案夾中,可以自定義修改檔案夾名。
*/

/*
#模闆test.conf檔案:
#鍵對應的值可以不用引号括起來
title = Welcome to Smarty!!
cutoff_size = 40

[china]
language = chinese

[england]
language = english

#[china],[england]為标簽,未設定标簽的鍵值為全局的隻要調用該配置檔案就可以在模版中使用,設定了标簽的鍵值隻有在調用配置檔案時指定了對應标簽才可以使用
#在PHP源檔案調用配置檔案語句$smarty->configLoad('test.conf', $sections = 'england');該語句下面調用的模版才可以使用該配置檔案,通過$sections屬性指定使用哪個标簽下的鍵和值
#$sections參數可以不寫,預設值為null,$smarty->configLoad('test.conf')則隻使用全局的鍵值,而不能使用标簽下的鍵值
#在模版下通過{config_load file="test.conf" section="china" scope="global"}語句調用配置檔案
#section屬性可以不寫,預設是null,scope屬性必須寫{config_load file="test.conf" scope="global"}
#section屬性可賦三種值
#local 隻有目前模版可以使用該配置檔案
#parent 隻有目前模版引入該配置檔案語句後包含的模版中,或在php源檔案中smarty對象調用該配置檔案後調用的模版中可以使用該配置檔案中的鍵值
#global 測試效果和parent相同
#在模版中通過{#language#}來使用鍵值,也可以通過{$smarty.config.language}來通路配置檔案鍵值
#PHP源檔案中可以使用$smarty->getConfigVars('language')或$smarty->getConfigVariable('language')來擷取鍵值,$smarty->getConfigVars('language')擷取的還可能是數組
*/


/*
tpl檔案中常用函數
tpl檔案:
<!--将capture标簽括起的頁面顯示内容存在capture指定的testCapture中 -->
<!--當達到指定條件時可通過 {$smarty.capture.testCapture} 将内容輸出出來 -->
{capture name="testCapture"}
{include file="f1.tpl"}
{/capture}

{if true}
{$smarty.capture.testCapture}
{/if}



{if $name == "wang"}

Welcome wang.

{elseif $name == "zhang"}

Welcome zhang.

{else}

Welcome, whatever you are.

{/if}
{*操作符可以是 ==,>= 等也可以是 eq,ne等*}



{for $x=0; $x<count($testArr); $x++}
{$x}
{/for}
{*for循環,類似PHP代碼*}


{$x=0}
{while $x<count($testArr)}
{$x++}
{/while}
{*While循環,也類似PHP代碼。*}


<!--name和key屬性可不寫-->
{foreach name="testForeach" from=$testArr key=arId item=arVal}
{$arId}對應的值為:{$arVal}
<br>
{$smarty.foreach.testForeach.index}   <!--(循環内部使用)顯示目前循環的索引,如果數組為空,傳回-1-->

{$smarty.foreach.testForeach.iteration}    <!--(循環内部使用)顯示目前的循環次數-->

{$smarty.foreach.testForeach.first} <!--(循環内部使用)如果為第一次循環,傳回true-->

{$smarty.foreach.testForeach.last} <!--(循環内部使用)如果為最後一次循環,傳回true-->

{$smarty.foreach.testForeach.total} <!-(循環内外部使用)顯示循環的總次數-->
<br>
{foreachelse}  <!--$testArr數組變量沒有值時(0個元素)執行。-->
$testArr is null
{/foreach}

{*也可以如下兩種類PHP格式*}
{foreach $testArr as $n}
{$n}
{/foreach}

{foreach $testArr as $key=>$n}
{$key}
{/foreach}



{$sectionArr = [0=>"a",4=>"b","c","d","e",6,7,8,9,10,11,12,13,14,15,16]}
{section name="testSection" loop=$sectionArr start=0 step=4 max=6 show=true}

{$smarty.section.testSection.index}- <!--目前循環到的數組的鍵值-->
{$sectionArr[testSection]}- <!--目前循環到的數組的元素值-->
{$smarty.section.testSection.iteration}-<!--目前section循環的次數,從1計起-->
<br/>

{sectionelse}
$sectionArr is null
{/section}
<!--section循環适用于純int型鍵值的數組-->
<!--給loop賦一個要循環的數組,start指定從數組指定鍵值開始循環,step指定數組下次循環的鍵值與本次循環鍵值之差,max指定循環最大次數,show指定是否循環false的話直接跳到執行sectionelse-->
<!--Section的内置變量與foreach 相同-->

*/


/*
tpl模闆檔案:
{literal}

<script type="text/javascript">
function a(){
    alert("this is script");
}
a();
</script>

{/literal}
{*
literal 标簽區域内的資料将被當作網頁html文本處理,此時模闆将忽略且不分析其内部的所有字元資訊。
該特性用于顯示有可能包含大括号等字元資訊的 js、css 。當這些資訊處于 {literal}{/literal} 标簽中時,模闆引擎将不分析它們,而直接顯示。
*}

*/

//PHP檔案:
//$smarty->setDebugging(true);//對後續調用的模闆進行調試。
//$smarty->getDebugging();//得到目前是否進行調試,預設false
//或在需要調試的模版中寫入{debug}

/*
模闆檔案:

smarty3.0支援了模版繼承系統,例如
f1.tpl:
<html>
<body>

{block name='top'} f1.header<br />{/block}
{block name='middle'} f1.middle<br />{/block}
{block name='buttom'} f1.buttom<br />{/block}

</body>
</html>

f2.tpl:
{extends file="f1.tpl"}
{block name='top'} f2.header<br />{/block}
{block name='other'} it can`t be show <br />{/block}
{*
如果f2.tpl中沒有block标簽,或f2.tpl中沒有和f1.tpl中相同命名的block标簽,則f2.tpl完整引入顯示f1.tpl中所有内容包括block标簽的内容,而f2.tpl中所有内容将忽略
如果f2.tpl中有和f1.tpl中同名block标簽,則在f2.tpl顯示時f2.tpl中block标簽内容将覆寫f1.tpl中同名block标簽的内容,在f2.tpl頁面顯示時,内容仍将按f1.tpl設定的格式位置顯示,f2.tpl其他所有文本包括未同名的block标簽及其内容都将被忽略,不顯示。
block标簽的内容隻會覆寫父模版中同名block标簽的内容,或在子模版中顯示,在本頁面中如果沒有調用父模版或父模版中沒有要覆寫的同名block标簽,block标簽内容在本頁面中不顯示
這種繼承支援多檔案,多重繼承,意味着可以無限的繼承下去
*}


{fetch file="http://www.126.com" assign="testAssign"}
{$testAssign}
{fetch file="http://www.126.com"}
{*fetch可以引用外部http,ftp的頁面,如指定assign的值則把引用的内容存在指定名的變量中,否則在哪有fetch在哪顯示*}
*/

//php頁面:
//調用模版也可以使用此方法,在輸出前做一些處理
//$output = $smarty->fetch("index.tpl");
//do something with $output here對将要輸出的内容進行處理
//echo $output;//然後将模闆輸出

/*
模闆中送出表單
<form name="input" action="file.php" method="post">
action屬性可以直接寫要送出到的php檔案名,或者不寫空action=""則送出到調用該模闆的php檔案中
*/


//連接配接資料庫
mysql_connect("localhost","root","root");
mysql_select_db("test");
$smarty->assign('webDir',$_SERVER['DOCUMENT_ROOT']);//$_SERVER['DOCUMENT_ROOT']為目前項目檔案夾的絕對路徑
//配置JQuery的src路徑最好寫絕對路徑或寫要運作檔案能找到該JQuery的相對路徑因為要編譯成編譯檔案,而編譯後的檔案和原路徑環境不一樣
?>
<script type="text/javascript" src="http://localhost/Smarty/demo/JS/jquery-1.7.2.min.js"></script>