<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                ## 新版模板引擎特性和使用方法 新版的sp框架,已經集成了一個非常輕量級的模板引擎,通過120行左右的代碼,實現兼容Smarty開發中最常用的語法,是代替Smarty的首選。 > 絕大部分開發過程中,我們用到Smarty引擎的功能只是Smarty的百分之一代碼量不到,并且Smarty越來越臃腫。所以我們開發了新的模板引擎,并且內置在框架內,僅僅120行的代碼,實現了日常開發全部用到的模板功能。 ### 特性 **編譯** - 模板在第一次框架執行時,會被編譯成php文件并保存下來,之后除非模板文件有修改,否則會一直使用編譯后的php文件,極大節省了資源。 - 模板編譯成php文件更方便opcode緩存,性能非常好。 - 當模板的其中一部分被修改后,會觸發局部編譯,僅僅針對部分頁面進行編譯,也很好地節省了資源。 **目錄** - 編譯目錄在protected/tmp,模板目錄在protected/view。protected/view也稱為模板根目錄。 - 目錄均為默認配置,只有在SAE環境下需要配置'view' => array('compile_dir'=>SAE_TMP_PATH),具體參考本手冊。 **自帶防跨站腳本攻擊XSS** - 每個輸出到頁面的模板變量,默認都會被進行htmlspecialchars()的轉換,以保證輸入腳本不會被執行。 - 只有在單個變量后面加入nofilter屬性后才會被取消轉換原樣輸出,但這時候就需要開發者謹慎使用了。 > php自帶的htmlspecialchars()函數會將'&','"',"'",'<','>'轉換成對應的HTML標記。 ### 使用模板 **賦值** 在控制器內,可以簡單地使用$this->foo=bar的方法將變量值傳給模板使用。 如 $this->foo = "bar"; 那么模板內就可以使用<{$foo}>變量了。 **顯示模板** 控制器內通過$this->display("模板文件名")的方式進行模板的顯示。 如 模板是 protected/view/guestbook.html 文件,要在控制器顯示即可用以下代碼: $this->display("guestbook.html"); 就可以顯示出來。 > 這里protected/view也稱為模板根目錄。 如果是模板目錄內還有子目錄,即可在display里面帶上子目錄。 如 模板是 protected/view/main/index.html 文件,那么: $this->display("main/index.html"); > display()使用的路徑均以模板根目錄為開始。 **自動顯示模板** sp框架的模板自動輸出可以讓我們不需要使用display語句就可以將模板輸出, 對代碼本身而言是簡化了不少,對開發者而言也更方便了。 > 舊版框架廣受好評的自動模板輸出,新版也繼承了,而且是內置的,不需要配置。 在模板根目錄里面,把模板名稱設置為“控制器名_方法名.html”,對應控制器/方法就不需要display(),而直接輸出此模板。 如模板目錄內有名為:“main_index.html”的模板,那么MainController/actionIndex()里面,不需要調用$this->display()方法,也會自動輸出“main_index.html”的模板。 - 模板名必須是“控制器_方法名.html”。無需配置,框架會自動檢測有無匹配名稱的模板,進行顯示。 - 如果控制器方法內已經調用過$this->display()來顯示模板,那么即使存在對應名稱的模板,也不會自動顯示。 - 該功能也同時支持modules模塊開發,但需要多一級路徑,如admin模塊下的MainController/actionIndex(),那么對應的自動顯示的模板文件路徑是:protected/view/admin/main_index.html。注意這里多了admin一級目錄。 [例子下載](images/8.zip) **自動顯示模板的最佳實踐**是:在比較簡單甚至沒有內容只是顯示模板的頁面上,可以盡量多地使用自動模板(如關于網站、介紹我們等頁面)。如果是模板賦值較多,邏輯較復雜的頁面,建議是盡量使用$this->diplay()進行顯示,這樣邏輯更清晰。 **layout布局** layout布局也是比較方便于使用模板的輔助功能,主要是解決頁面之間共同的大結構的模板問題。 > 舊版框架里面,一般解決頁面共用結構,是通過在各模板上面,前面include一個header.html,后面再include一個footer.html來實現的。 > 不過這樣首先體驗很糟糕,畢竟每個頁面都需要寫上下兩個include,忘記了就麻煩。而且要在不同的模板動態調整大結構也是比較麻煩的,比如說使用不同的header.html。 > 當然,通過一些小技巧,舊版框架還是能實現這個layout布局的。 新版自帶layout布局的模式,就可以很好解決此問題。 layout布局,可以通過一個可靈活變動的布局模板,然后自動成為其他模板的大結構。 - 布局模板可以在控制器內定義,生效訪問根據控制器本身的范圍,比如說MainController那么只有Main控制器里面的方法才會生效,如果是BaseController那么但凡繼承BaseController都會生效(除非單獨的控制器自己再覆蓋定義一個)。 - 生效范圍內的模板,都不再需要寫外面的結構,可以直接寫里面的結構。 - 模板輸出的時候,布局模板會在外面,嵌套了里面的各個模板。 - **當$layout被設置成空的時候,那么當前頁面就不會啟用布局模板。**對于一些比較特殊的頁面,如Ajax請求帶模板的頁面,比較方便哦。 [例子下載](images/8.zip)(和上面的自動顯示模板的例子是同一個) 使用layout布局我們先要準備兩個事情: 1. 要賦值給控制器的$layout這個成員變量,值是一個模板的文件名。如例子里面是在BaseController.php里面,$layout="layout.html"。 2. 在模板目錄,我們要創建剛才賦值的文件名的文件。例子里面我們創建了protected/view/layout.html。 我們看看layout.html里面內容是什么: <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>layout演示</title> <link href="/i/css/bootstrap.min.css" rel="stylesheet"> </head> <body> <br /> <div class="container"> <nav class="navbar navbar-default"> <div class="container-fluid"> <div class="navbar-header"> <a class="navbar-brand" href="#"> Layout演示 </a> </div> </div> </nav> <{include file=$__template_file}> </div> </body> </html> 主要關注 <{include file=$__template_file}>這句,這是布局模板的關鍵所在。 然后我們看看其他的模板: main_index.html <div class="jumbotron"> <h1>Hello, world!</h1> <p>This is a simple hero unit, a simple jumbotron-style component for calling extra attention to featured content or information.</p> <p><a class="btn btn-primary btn-lg" href="<{url c="view" a="index"}>" role="button">Learn more</a></p> </div> 可以發現main_index.html和view_index.html都只有中間的HTML,沒有包括頭尾的HTML。(也沒有header.html和footer.html什么的) 在頁面輸出的時候,我們查看源碼,如http://localhost/main/index <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>layout演示</title> <link href="/i/css/bootstrap.min.css" rel="stylesheet"> </head> <body> <br /> <div class="container"> <nav class="navbar navbar-default"> <div class="container-fluid"> <div class="navbar-header"> <a class="navbar-brand" href="#"> Layout演示 </a> </div> </div> </nav> <div class="jumbotron"> <h1>Hello, world!</h1> <p>This is a simple hero unit, a simple jumbotron-style component for calling extra attention to featured content or information.</p> <p><a class="btn btn-primary btn-lg" href="http://localhost/view/index" role="button">Learn more</a></p> </div> </div> </body> </html> 可以發現layout.html的內容已經在頁面上,而且main_index.html的內容是嵌在中間的。 ![layout示意圖](https://box.kancloud.cn/309f813c6abd65e30b73588f878c8ce5_556x562.jpg) > 例子里面需要注意一下的是BaseController.php文件的$layout變量。 ### 模板語法 本章介紹新版模板引擎的全部功能,我們會發現新版模板引擎的語法和Smarty比較像,而且包含了日常開發中用到的Smarty的功能。 **限定符** 模板引擎的限定符是<{和}>,而且一般不能進行修改,除非直接使用View類。 限定符的意思是在模板頁面里面,在<{ 和 }> 中間的代碼,均被視為模板語法,會被模板引擎進行編譯。 > 也可以把限定符內的內容理解成類似php的語法代碼,在最終顯示的頁面上,是看不到這些代碼的,只能看到這些代碼輸出的結果。 模板引擎的全部語法,都是指在模板內的限定符中間編寫的代碼規則。 **注釋** 模板內的注釋寫法如下: <{*這里是一個注釋*}> 注釋的作用只是寫在代碼頁面上供提示之用,不會執行也不會輸出到頁面上。 **變量顯示** 在控制器內通過$this->foo=bar的方式傳值的變量,在模板內都可以直接通過$foo的方式使用。 如MainController.php <?php class MainController extends BaseController { function actionIndex(){ $this->myval = "123"; $this->display("main_index.html"); } } 在main_index.html模板即可通過: 傳值是:<{$myval}> 結果是:傳值是123 這里的變量可以是一切php的變量,包括數字/字符串/數組等。 **變量自動過濾及避免過濾** 從控制器中傳遞到模板的變量,如果直接顯示將默認進行HTML轉碼,功能類似PHP函數htmlspecialchars(); '&' (和符號) 轉成 '&amp;' '"' (雙引號) 轉成 '&quot;' "'" (單引號) 轉成 '&#039;' (或者 &apos;) '<' (小于號) 轉成 '&lt;' '>' (大于號) 轉成 '&gt;' 如MainController.php <?php class MainController extends BaseController { function actionIndex(){ $this->myval = "<script>alert('攻擊代碼');</script>"; $this->display("main_index.html"); } } 在main_index.html模板: 傳值是:<{$myval}> 顯示的HTML源碼是: 傳值是:&lt;script&gt;alert(&#039;攻擊代碼&#039;);&lt;/script&gt; 有時我們也需要讓變量直接顯示成HTML,而不進行過濾的,那么在保證變量本身安全的前提下,我們可以通過nofilter語法來避免過濾。 還是上述的例子,但是在模板內是: 傳值是:<{$myval nofilter}> 加入了nofilter的修飾符,然后顯示是: ![nofilter](https://box.kancloud.cn/5274dc4d4b3a5f9c4f5ddb64c33795f4_550x260.jpg) 顯示的HTML源碼是: 傳值是:<script>alert('攻擊代碼');</script> **變量賦值** 模板內可以通過等號進行變量賦值,如: <{$foo = $myval + 2}> <{$foo}> 那么$foo會輸出125 (123+2)。 **使用常量** PHP常量可以兩種方式在模板內使用,請自行選擇一種: ***使用#語法*** 模板中可以使用#語法來使用常量:如<{#ROOT}>,例子: MainController.php <?php class MainController extends BaseController { function actionIndex(){ define("MY_CONSTANT", "show the money"); $this->display("main_index.html"); } } 在main_index.html模板: 顯示常量:<{#MY_CONSTANT}> ***使用傳值方式使用常量*** 如果不想使用#方式來顯示常量,可以通過賦值的方式來使用。 > 有時候在一個模板內使用太多自定義的語法是不太好的,會增加團隊學習成本,故常量的顯示方法可以自行選擇。 例子: MainController.php <?php class MainController extends BaseController { function actionIndex(){ define("MY_CONSTANT", "show the money"); $this->constant = MY_CONSTANT; $this->display("main_index.html"); } } 在main_index.html模板: 顯示常量:<{$constant}> 這里先將全部用戶定義常量傳給模板變量,然后在模板內直接使用。傳值這個步驟可以放控制器,要做到全局也可以放BaseController。如: <?php class BaseController extends Controller{ public $layout = "layout.html"; // 通過繼承將display重寫,使得可以傳入常量的數組 function display($tpl_name, $return = false){ $this->constant = MY_CONSTANT; parent::display($tpl_name, $return); } } **數組點號** 變量輸出時,如果是數組,那么可以通過傳統數組的方括號來顯示值,也可以通過點號來顯示。 如MainController.php <?php class MainController extends BaseController { function actionIndex(){ $this->myval = array("num"=>10086); $this->display("main_index.html"); } } 那么在模板內可以使用以下兩種顯示方式: <{$myval["num"]}> 等同于 <{$myval.num}> 顯示的結果是:10086 等同于 10086 **循環foreach** 新版模板引擎支持php的foreach語法,但是稍微有點不一樣。 > <{/foreach}>是foreach的結束符 如MainController.php <?php class MainController extends BaseController { function actionIndex(){ $this->myarr = array( "one" => "100", "two" => "200", "three" => "300", ); $this->display("main_index.html"); } } main_index.html <{foreach $myarr as $k => $v}> <p><{$k}> => <{$v}></p> <{/foreach}> 輸出: ![foreach結果](https://box.kancloud.cn/b86f76812804c1136e0a898471d0562b_136x103.jpg) 當然,不要key的數組foreach也是可以的: <{foreach $myarr as $v}> <p><{$v}></p> <{/foreach}> ![foreach結果](https://box.kancloud.cn/34a1c0de54949c2161ac78e4362c7336_79x104.jpg) **foreach的自帶值** 模板的foreach有一些比較特殊的值,方便平時編程使用的。 自帶值|意義|作用 ---|---|--- $v@index|循環索引,從0開始按循環次數遞增|用于判斷當前循環次數,如隔行換底色等 $v@iteration|循環次數,從1開始遞增,等同于$v@index + 1|用于顯示序號 $v@first|當第一次循環,值是true,之后一直是false|用于判斷當前循環是否循環的最開始第一次,如制作表格的表頭之類的 $v@last|當循環到最后一次,值為true,未到最后則是false|用于判斷當前循環是否最后一次循環,比如說有時候循環最后一行的收尾處理 $v@total|循環數組的總次數,等于與count(數組)|顯示總數,在一開始就知道總數挺方便的 示例: <{foreach $myarr as $v}> <p>第<{$v@iteration}>個值:<{$v}> <{if $v@first == true}> (這里是開始一行) <{/if}> <{if $v@last == true}> (這里是最后一行) <{/if}> </p> <{/foreach}> 結果: ![foreach結果](https://box.kancloud.cn/38aa7bd3b3c903151c440e22540370e1_301x105.jpg) **多維數組的顯示** 示例: <?php class MainController extends BaseController { function actionIndex(){ $this->myarr = array( array( array( 'name' => 'apple', 'count' => '1000', ), array( 'name' => 'banana', 'count' => '2000' ), ), array( array( 'name' => 'cat', 'count' => '5000', ), array( 'name' => 'dog', 'count' => '100' ), ), ); $this->display("main_index.html"); } } 模板: <{foreach $myarr as $arr1}> 第<{$arr1@iteration}>列 <{foreach $arr1 as $arr2}> <{foreach $arr2 as $k => $v}> <p><{$k}>:<{$v}></p> <{/foreach}> <{/foreach}> <{/foreach}> 結果: ![多維數組結果](https://box.kancloud.cn/157bc20c86817fdbc54549123fe3d563_199x287.jpg) **break,continue** foreach循環里面可以使用php語法的break和continue,使用方法是: <{break}> 和 <{continue}> 作用跟php內使用完全一致。 **if判斷** 新版模板引擎支持if判斷,包括if,elseif,else,<{/if}>(結束符)。 如: <?php class MainController extends BaseController { function actionIndex(){ $this->myval = 500; $this->mybool = false; $this->display("main_index.html"); } } 模板: <p> <{if $myval > 1000}> myval大于1000 <{elseif $myval > 100}> myval小于等于1000,大于100 <{else}> myval小于等于100 <{/if}> </p> <p> <{if $mybool}> mybool是true <{else}> mybool是false <{/if}> </p> 結果: ![foreach結果](https://box.kancloud.cn/9a2356c20c3d1324dfb9d054fabab0f2_229x78.jpg) **include包含模板** 模板中可以通過include語法進行模板的包含。 - 包含的模板路徑以模板根目錄為基礎,一般是protected/view。 - 包含的模板里面不能有包含原來模板的語句,否則會造成死循環。 語法: <{include file="inner.html"}> 一般include是用于包含公共HTML片段,使得不需要相同的代碼寫多次,而且修改也能比較方便地修改一個地方即可。 **函數調用方法** 新版框架可以直接調用php函數輸出。不再需要像舊版一樣需要注冊函數。 > 理論上,注冊一個函數來使用是很不合理的事情,畢竟模板內也是php,也能執行php函數。 **一般建議模板內調用的函數,都是可以直接輸出結果的。** 示例: <?php class MainController extends BaseController { function actionIndex(){ // strtotime可以通過字符串取得時間戳 // 這里取上個星期天的時間戳 $this->mytime = strtotime("last sunday"); $this->display("main_index.html"); } } 模板調用date()函數輸出: 上個星期天是<{date("Y年m月d日", $mytime)}> 結果: ![foreach結果](https://box.kancloud.cn/356ffe94efc34a8a797561e0393b7a3a_295x49.jpg) **URL地址構造函數url()** 新版框架還支持另一種函數調用方式,我們通過最常用的url()地址構造函數來講解一下: 在模板內使用url()函數是這樣的: <a href="<{url c="main" a="index"}>">返回首頁</a> 這里有一些特點: - url()函數并不是通過類似date()函數的函數調用的。 - 參數是類似鍵值對(key-value)的方式賦值。 觀察一下url()函數的代碼,會發現: function url($c = 'main', $a = 'index', $param = array()){ if(is_array($c)){ $param = $c; $c = $param['c']; unset($param['c']); $a = $param['a']; unset($param['a']); } ... 參數$c做了一個特殊的處理:判斷$c(第一個參數)是否數組,如果是的話,將數組內和參數同名鍵的值取出來賦值給同名參數。 也就是說,第一個參數$c實際上是一個帶了完整三個參數的數組。 所以,如果需要寫一個類似url()的函數,那么它的第一個參數數組,就是全部的參數的數組。 而且這個函數在模板調用時,就可以直接通過鍵值對的方式來賦值參數了。 有時我們需要對URL的中文進行URLdecode處理,如某些情況下的JS或者ajax傳遞漢字或特殊值參數時,會發現<{url}>的調用將漢字或特殊值轉換成%20的URL編碼后的樣子,不利于JS的編寫和參數構造。 這個時候我們可以通過函數的方式來將URL解碼,那么輸出到頁面上“漢字”就會保持原樣。 <a href="<{urldecode(url("search", "index", array("search" => "漢字")))}>">返回首頁</a> 這里是直接用了urldecode()函數,而url()函數也是用了它的原始的版本。 **臨時目錄不可寫錯誤** 很多時候在linux上使用新版框架會產生以下錯誤提示: Err: Directory "somedir/tmp" is not writable or readable 原因是protected/tmp目錄不可寫導致的。 解決方法是:將protected/tmp目錄的權限設置成777。 **修改限定符** 在新版中,左右限定符(<{和}>)是默認的。因其可以在頁面上很好地跟Javascript腳本做區分。不過如果希望自行修改限定符,可以通過以下方法: // 這里是BaseController里面的init()方法 function init(){ $compile_dir = isset($GLOBALS['view']['compile_dir']) ? $GLOBALS['view']['compile_dir'] : APP_DIR.DS.'protected'.DS.'tmp'; $this->_v = new View(APP_DIR.DS.'protected'.DS.'view', $compile_dir, '{', '}'); // ..其他代碼.. } **模板中CSS和JS的路徑** > 圖片、CSS和Javascript文件,我們通常稱其為“媒體文件”。 媒體文件在頁面上使用,可以有兩種路徑:相對路徑、絕對路徑。 ***相對路徑***:指的是媒體文件相對于瀏覽器訪問的當前目錄的路徑。 比如說: http://www.speedphp.com/bbs/forum-6-1.html 這個網址瀏覽器的當前訪問目錄,是: http://www.speedphp.com/bbs/ 如果該網頁上面有這樣一張圖片: <img src="images/logo.gif" alt="" /> 那么,這張圖片就稱為“相對路徑”,可以認為,通過以下地址就可以訪問到這張圖片: http://www.speedphp.com/bbs/images/logo.gif 還有更多例子: <script type="text/javascript" src="js/jquery.js"></script> <link rel="stylesheet" href="css/style.css" type="text/css" media="screen" /> <img src="images/logo.gif" alt="" /> “./”點斜杠是相對路徑:(注意是點+斜杠) <script type="text/javascript" src="./js/jquery.js"></script> <link rel="stylesheet" href="./css/style.css" type="text/css" media="screen" /> <img src="./images/logo.gif" alt="" /> 相對路徑在使用中會有個缺點,當前頁面的訪問目錄如果修改,那么頁面上的媒體文件路徑也可能要修改,不然就會找不到媒體文件。 所以,一般建議只在當前頁面訪問目錄能確定不會修改的情況下,才直接在模板上面使用相對路徑。 > 有些時候,當一套speedphp的程序,從原來的未開啟urlrewrite到開啟后,產生頁面上圖片或者css文件錯亂的情況,就有可能是因為使用了相對路徑;解決的方案是修改成絕對路徑,或者重新調整媒體文件的路徑。 ***絕對路徑***:指的是媒體文件相對網站根目錄的路徑。 絕對路徑有兩種情況,單斜杠開頭的媒體文件地址,或者是http://開頭的完整的媒體文件地址。 以下都是絕對路徑的例子: <script type="text/javascript" src="/js/jquery.js"></script> <link rel="stylesheet" href="/css/style.css" type="text/css" media="screen" /> <img src="/images/logo.gif" alt="" /> <script type="text/javascript" src="http://www.speedphp.com/js/jquery.js"></script> <link rel="stylesheet" href="http://www.speedphp.com/css/style.css" type="text/css" media="screen" /> <img src="http://www.speedphp.com/images/logo.gif" alt="" /> 由于在絕對路徑中,媒體文件是相對于網站根目錄,所以無論在哪個頁面上,用絕對路徑都能找到這個媒體文件。 如果對于媒體文件地址比較困惑的情況,建議直接用絕對路徑。 > url()函數產生的網址,也是http://開頭的絕對路徑地址。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看