轉載:http://bbs.cnaust.com/archiver/?tid-4849.html

          PHPliB類詳解

          自已的BLOG空間打不開了,放些資料在這。


          <?php??
          /*??
          * PHPlib模板7.4中文版(不足之處還請各位指正)??
          * (C) Copyright 1999-2000 NetUSE GmbH??
          * Kristian Koehntopp??
          * 彭贊群注釋于2004年6月,QQ:9537075 TEL:13787877670??
          * Email:mylovepzq@163.com??
          */??


          /*這里是定義類Template*/??
          class Template??
          {? ?
          /* 如果設置了,則輸出參數 */??
          var $classname = "Template";??
          var $debug = false; //是否調試??
          var $root = ".";//root為模板文件的存放目錄??
          var $file = array(); //包含了所有的模板文件名和模板名的數組??
          var $varkeys = array(); //存放文本元素的鍵名??
          var $varvals = array(); //存放文本元素的值??
          var $unknowns = "remove";? ?
          /* "remove" => 刪除未定義的變量 "comment" => 將未定義的變量變成注釋 "keep" => 保留未定義的變量 */??
          var $halt_on_error = "yes";??
          /* "yes" => 退出 "report" => 報告錯誤,繼續(xù)運行* "no" => 忽略錯誤*/??
          var $last_error = "";??
          /* 上一次的錯誤保存在這里 */??
          /* public: 構造函數??
          * root: 模板目錄??
          * unknowns: 如何處理未知的變量(譯者:變量定義為{ name })??
          */??


          /*這里是定義函數Template*/??
          function Template($root = ".", $unknowns = "remove")? ?
          {? ?
          if ($this->debug & 4)? ?
          {? ?
          echo "<p><b>模板:</b> root = $root, unknowns = $unknowns</p>\n";??
          }??
          $this->set_root($root);//默認將文件目錄設置為相同的目錄??
          $this->set_unknowns($unknowns);//unknowns默認設置為"remove"??
          }??


          /*這里是函數set_root*/??
          function set_root($root)??
          {? ?
          if ($this->debug & 4)? ?
          {? ?
          echo "<p><b>設置根目錄:</b> root = $root</p>\n";??
          }??
          if (!is_dir($root))??
          {? ?
          $this->halt("設置根目錄: $root 不是一個無效的目錄.");??
          return false;??
          }??
          $this->root = $root;??
          return true;??
          }??


          //這里是函數set_unknowns,即對未知變量的處理??
          function set_unknowns($unknowns = "remove")??
          {? ?
          if ($this->debug & 4)??
          {? ?
          echo "<p><b>未知的:</b> 未知 = $unknowns</p>\n";??
          }??
          $this->unknowns = $unknowns;??
          }??


          /*這里是函數set_file.......................................................*/??
          //該方法在數組file中根據$varname提供的鍵名加入值??
          function set_file($varname, $filename = "")??
          {? ?
          if (!is_array($varname))//如果varname是數組??
          {? ?
          if ($this->debug & 4)??
          {? ?
          echo "<p><b>設置文件:</b> (with scalar) varname = $varname, filename = $filename</p>\n";??
          }??
          if ($filename == "")//如果文件名為空,輸出錯誤??
          {? ?
          $this->halt("設置文件:變量名 $varname 文件名是空的.");??
          return false;??
          }??
          $this->file[$varname] = $this->filename($filename);??
          }? ?
          else??
          {? ?
          reset($varname);//將varname的鍵名作為file數組的鍵名??
          //將鍵名對應的值作為file數組的值??
          while(list($v, $f) = each($varname))??
          {? ?
          if ($this->debug & 4)??
          {? ?
          echo "<p><b>set_file:</b> (with array) varname = $v, filename = $f</p>\n";??
          }??
          if ($f == "")??
          {? ?
          $this->halt("set_file: For varname $v filename is empty.");??
          return false;??
          }??
          $this->file[$v] = $this->filename($f);??
          }??
          }??
          return true;??
          }??


          //該方法取出某個父模板文件中的一個子模板??
          //將其作為塊來加載??
          //并用另外一個模板變量取代之??
          /* public: set_file(array $filelist)??
          * comment: 設置多個模板文件??
          * filelist: (句柄,文件名)數組??
          * public: set_file(string $handle, string $filename)??
          * comment: 設置一個模板文件??
          * handle: 文件的句柄??
          * filename: 模板文件名??
          */??
          function set_block($parent, $varname, $name = "") {? ?
          if ($this->debug & 4) {? ?
          echo "<p><b>set_block:</b> parent = $parent, varname = $varname, name = $name</p>\n";??
          }??
          if (!$this->loadfile($parent)) {? ?
          $this->halt("set_block: unable to load $parent.");??
          return false;??
          }??
          if ($name == "") {? ?
          $name = $varname;//如果沒有指定模板變量的值就用子模板名作為模板變量名??
          }??

          $str = $this->get_var($parent);??
          $reg = "/[ \t]*<!--\s+BEGIN $varname\s+-->\s*?\n?(\s*.*?\n?)\s*<!--\s+END $varname\s+-->\s*?\n?/sm";??
          preg_match_all($reg, $str, $m);??
          $str = preg_replace($reg, "{ " . "$name }", $str);??
          $this->set_var($varname, $m[1][0]);??
          $this->set_var($parent, $str);??
          return true;??
          }??


          //該方法向Varname和varkeys數組中添加新的鍵一值對??
          /* public: set_var(array $values)??
          * values: (變量名,值)數組??
          * public: set_var(string $varname, string $value)??
          * varname: 將被定義的變量名??
          * value: 變量的值??
          */??
          function set_var($varname, $value = "", $append = false) {? ?
          if (!is_array($varname))//如果不是陣列??
          {? ?
          if (!empty($varname)) //如果是空的??
          {? ?
          if ($this->debug & 1) {? ?
          printf("<b>set_var:</b> (with scalar) <b>%s</b> = ’%s’<br>\n", $varname, htmlentities($value));??
          }??
          $this->varkeys[$varname] = "/".$this->varname($varname)."/";??
          if ($append && isset($this->varvals[$varname])) {? ?
          $this->varvals[$varname] .= $value;??
          } else {? ?
          $this->varvals[$varname] = $value;??
          }??
          }??
          } else {? ?
          reset($varname);??
          while(list($k, $v) = each($varname)) {? ?
          if (!empty($k)) {? ?
          if ($this->debug & 1) {? ?
          printf("<b>set_var:</b> (with array) <b>%s</b> = ’%s’<br>\n", $k, htmlentities($v));??
          }??
          $this->varkeys[$k] = "/".$this->varname($k)."/";??
          if ($append && isset($this->varvals[$k])) {? ?
          $this->varvals[$k] .= $v;??
          } else {? ?
          $this->varvals[$k] = $v;??
          }??
          }??
          }??
          }??
          }??


          //定義函數clear_var??
          function clear_var($varname) {? ?
          if (!is_array($varname))//如果varname不是陣列??
          {? ?
          if (!empty($varname)) //如果是空的??
          {? ?
          if ($this->debug & 1) {? ?
          printf("<b>clear_var:</b> (with scalar) <b>%s</b><br>\n", $varname);??
          }??
          $this->set_var($varname, "");??
          }??
          } else {? ?
          reset($varname);??
          while(list($k, $v) = each($varname)) {? ?
          if (!empty($v)) {? ?
          if ($this->debug & 1) {? ?
          printf("<b>clear_var:</b> (with array) <b>%s</b><br>\n", $v);??
          }??
          $this->set_var($v, "");??
          }??
          }??
          }??
          }??


          /*這里是函數unset_var,刪除變量的定義*/??
          function unset_var($varname) {? ?
          if (!is_array($varname)) {? ?
          if (!empty($varname)) {? ?
          if ($this->debug & 1) {? ?
          printf("<b>unset_var:</b> (with scalar) <b>%s</b><br>\n", $varname);??
          }??
          unset($this->varkeys[$varname]);??
          unset($this->varvals[$varname]);??
          }??
          } else {? ?
          reset($varname);??
          while(list($k, $v) = each($varname)) {? ?
          if (!empty($v)) {? ?
          if ($this->debug & 1) {? ?
          printf("<b>unset_var:</b> (with array) <b>%s</b><br>\n", $v);??
          }??
          unset($this->varkeys[$v]);??
          unset($this->varvals[$v]);??
          }??
          }??
          }??
          }??


          //將模板文件中的變化內容替換成確定內容的操作,實現數據和顯示的分離??
          function subst($varname) {? ?
          $varvals_quoted = array();??
          if ($this->debug & 4) {? ?
          echo "<p><b>subst:</b> varname = $varname</p>\n";??
          }??
          if (!$this->loadfile($varname)) //裝載模板文件,如果出錯就停止??
          {? ?
          $this->halt("subst: unable to load $varname.");??
          return false;??
          }??

          reset($this->varvals);??
          while(list($k, $v) = each($this->varvals)) {? ?
          $varvals_quoted[$k] = preg_replace(array(’/\\\\/’, ’/\$/’), array(’\\\\\\’, ’\\\\$’), $v);??
          }??

          //讀入文件內容到字符串中并在下行對已知鍵值進行替換并返回結果??
          $str = $this->get_var($varname);??
          $str = preg_replace($this->varkeys, $varvals_quoted, $str);??
          return $str;??
          }??


          //同subst,只是直接輸出結果??
          function psubst($varname) {? ?
          if ($this->debug & 4) {? ?
          echo "<p><b>psubst:</b> varname = $varname</p>\n";??
          }??
          print $this->subst($varname);??

          return false;??
          }??


          //將varname代表的一個或多個文件中的內容完成替換??
          //存放在target為鍵值的varvals數組無素中或追加到其后??
          //返回值和sub相同??
          function parse($target, $varname, $append = false) {? ?
          if (!is_array($varname)) {? ?
          if ($this->debug & 4) {? ?
          echo "<p><b>parse:</b> (with scalar) target = $target, varname = $varname, append = $append</p>\n";??
          }??
          $str = $this->subst($varname);??
          if ($append) {? ?
          $this->set_var($target, $this->get_var($target) . $str);??
          } else {? ?
          $this->set_var($target, $str);??
          }??
          } else {? ?
          reset($varname);??
          while(list($i, $v) = each($varname)) {? ?
          if ($this->debug & 4) {? ?
          echo "<p><b>parse:</b> (with array) target = $target, i = $i, varname = $v, append = $append</p>\n";??
          }??
          $str = $this->subst($v);??
          if ($append) {? ?
          $this->set_var($target, $this->get_var($target) . $str);??
          } else {? ?
          $this->set_var($target, $str);??
          }??
          }??
          }??

          if ($this->debug & 4) {? ?
          echo "<p><b>parse:</b> completed</p>\n";??
          }??
          return $str;??
          }??


          //同parse方法,只是該方法將結果輸出??
          function pparse($target, $varname, $append = false) {? ?
          if ($this->debug & 4) {? ?
          echo "<p><b>pparse:</b> passing parameters to parse...</p>\n";??
          }??
          print $this->finish($this->parse($target, $varname, $append));??
          return false;??
          }??


          //返回所有的鍵一值對中的值所組成的數組??
          function get_vars() {? ?
          if ($this->debug & 4) {? ?
          echo "<p><b>get_vars:</b> constructing array of vars...</p>\n";??
          }??
          reset($this->varkeys);??
          while(list($k, $v) = each($this->varkeys)) {? ?
          $result[$k] = $this->get_var($k);??
          }??
          return $result;??
          }??


          //根據鍵名返回對應的鍵一值勤對應的值??
          function get_var($varname) {? ?
          if (!is_array($varname)) //如果不是陣列??
          {? ?
          if (isset($this->varvals[$varname])) //如果變量不存在??
          {? ?
          $str = $this->varvals[$varname];??
          } else {? ?
          $str = "";??
          }??
          if ($this->debug & 2) {? ?
          printf ("<b>get_var</b> (with scalar) <b>%s</b> = ’%s’<br>\n", $varname, htmlentities($str));??
          }??
          return $str;??
          } else {? ?
          reset($varname);??
          while(list($k, $v) = each($varname)) {? ?
          if (isset($this->varvals[$v])) {? ?
          $str = $this->varvals[$v];??
          } else {? ?
          $str = "";??
          }??
          if ($this->debug & 2) {? ?
          printf ("<b>get_var:</b> (with array) <b>%s</b> = ’%s’<br>\n", $v, htmlentities($str));??
          }??
          $result[$v] = $str;??
          }??
          return $result;??
          }??
          }??


          //如果加載文件失敗,返回錯誤并停止??
          function get_undefined($varname) {? ?
          if ($this->debug & 4) {? ?
          echo "<p><b>get_undefined:</b> varname = $varname</p>\n";??
          }??
          if (!$this->loadfile($varname)) {? ?
          $this->halt("get_undefined: unable to load $varname.");??
          return false;??
          }??

          preg_match_all("/{ ([^ \t\r\n }]+) }/", $this->get_var($varname), $m);??
          $m = $m[1];??
          //如果無法找到匹配的文本,返回錯誤??
          if (!is_array($m)) {? ?
          return false;??
          }??
          //如果能找到大括號中的非空字符,則將其值作為鍵值,組成一個新的數組??
          reset($m);??
          while(list($k, $v) = each($m)) {? ?
          if (!isset($this->varkeys[$v])) {? ?
          if ($this->debug & 4) {? ?
          echo "<p><b>get_undefined:</b> undefined: $v</p>\n";??
          }??
          $result[$v] = $v;??
          }??
          }??
          //如是該數組不為空就返回該數組,否則就返回錯誤??
          if (count($result)) {? ?
          return $result;??
          } else {? ?
          return false;??
          }??
          }??


          //完成對str的最后的處理工作,利用類的屬性unknowns來確定對模板中無法處理的動態(tài)部分的處理方法??
          function finish($str) {? ?
          switch ($this->unknowns) {? ?
          case "keep": //保持不變??
          break;??

          case "remove": //刪除所有的非控制符??
          $str = preg_replace(’/{ [^ \t\r\n }]+ }/’, "", $str);??
          break;??

          case "comment"://將大括號中的HTML注釋??
          $str = preg_replace(’/{ ([^ \t\r\n }]+) }/’, "<!-- Template variable \\1 undefined -->", $str);??
          break;??
          }??

          return $str;??
          }??


          //將參數變量對誚的數組中的值處理后輸出??
          function p($varname) {? ?
          print $this->finish($this->get_var($varname));??
          }??


          //將參數變量對應的數組中的值處理后返回??
          function get($varname) {? ?
          return $this->finish($this->get_var($varname));??
          }??


          //檢查并補充給定的文件名??

          function filename($filename) {? ?
          if ($this->debug & 4) {? ?
          echo "<p><b>filename:</b> filename = $filename</p>\n";??
          }??
          if (substr($filename, 0, 1) != "/")? ?
          //如果文件名不是以斜杠開頭,則表示是相對路徑,將其補充為完整的絕對路徑? ?
          {? ?
          $filename = $this->root."/".$filename;??
          }??
          //如果文件不存在??
          if (!file_exists($filename)) {? ?
          $this->halt("filename: file $filename does not exist.");??
          }??
          return $filename;//返回文件名??
          }??


          //對變量名進行處理,將正則表達式中的敏感字符變?yōu)檗D義字符,并在變量名兩端加上大括號??
          function varname($varname) {? ?
          return preg_quote("{ ".$varname." }");??
          }??


          //該方法根據varname加載文件到鍵一值對中??
          function loadfile($varname) {? ?
          if ($this->debug & 4) {? ?
          echo "<p><b>loadfile:</b> varname = $varname</p>\n";??
          }??

          if (!isset($this->file[$varname])) //如果沒有指定就返加錯誤??
          {? ?
          // $varname does not reference a file so return??
          if ($this->debug & 4) {? ?
          echo "<p><b>loadfile:</b> varname $varname does not reference a file</p>\n";??
          }??
          return true;??
          }??

          if (isset($this->varvals[$varname]))//如果已經加載了varname為名柄的文件,直接返回真值??
          {? ?
          if ($this->debug & 4) {? ?
          echo "<p><b>loadfile:</b> varname $varname is already loaded</p>\n";??
          }??
          return true;??
          }??
          $filename = $this->file[$varname];//句柄有效則取出對應的文件名??
          $str = implode("", @file($filename));//將文件的每一行連接成一個字符串??
          if (empty($str)) //字符串空說明文件空或者不存在,返回錯誤??
          {? ?
          $this->halt("loadfile: While loading $varname, $filename does not exist or is empty.");??
          return false;??
          }??
          if ($this->debug & 4) {? ?
          printf("<b>loadfile:</b> loaded $filename into $varname<br>\n");??
          }??
          $this->set_var($varname, $str);//如果文件不為空,用$varname作為句柄,str為變量名??
          //向鍵值對中添加新的鍵值??

          return true;??
          }??

          //將分析結果保存到文件中去??
          ??function savetofile ($dir,$varname){? ?
          ? ?$data=$this->finish($this->get_var($varname));??
          ? ?$fp=fopen($dir,"w+");??
          ? ?fwrite($fp,$data);??
          ??}??


          ??//清除已賦值數組??
          ? ?function renew(){? ?
          ? ? $this->varkeys=array();??
          ? ? $this->varvals=array();??
          ? ? $this->file=array();??
          ? ? }??


          //出錯提示并終止程序運行??
          function halt($msg) {? ?
          $this->last_error = $msg;??

          if ($this->halt_on_error != "no") {? ?
          $this->haltmsg($msg);??
          }??

          if ($this->halt_on_error == "yes") {? ?
          die("<b>終止.</b>");??
          }??

          return false;??
          }??


          //出錯提示??
          function haltmsg($msg) {? ?
          printf("<b>模板錯誤:</b> %s<br>\n", $msg);??
          }??

          }??
          ?>




          SOLO
          PHPLIB Template類的使用的.誠然,網絡上已經很多相關的話題了,但據我觀察,中文的資料實在不多,且大多是講的太籠統(tǒng),沒能全面闡述它的用法,即使看了還是一知半解.所以本文就期望通過對它的比較全面的介紹,讓你能達到入門的水平.
          何謂"模板"技術

          我們的最初觀察是將界面和實現代碼分離開來,這樣做的目的是將美工和程序員的工作分離開來.PHP的一個優(yōu)點是可以把PHP代碼嵌入HTML里面,這樣你就不必再把大段HTML代碼用函數print()輸出來.
          print("<table border=0 cellspacing=1 cellpadding=2 width=100%>");
          print("<tr>");
          print("<td>");
          print("我愛你 kiki");
          print("</td>");
          print("</tr>");
          print("</table>");
          這段代碼對界面維護來說是相當困難的,除非程序員做這樣事情且他對樣式表,HTML非常精通.取而代之的我們用
          <table border=0 cellspacing=1 cellpadding=2 width=100%>
          ? ? <tr>
          ? ?? ???<td>
          ? ?? ?? ?? ?<?php print("我愛你 kiki ");?>
          ? ?? ???</td>
          ? ? </tr>
          </table>
          這樣,做美工設計的只要不碰PHP代碼,就可以很方便地改變這個表格的樣式,如果使用dreamweaver等所見即所的工具,將會更加方便.

          現在的一個問題是,如果美工正在修改的話,程序員仍需要把這個文件取回來,才能改變里面的PHP代碼,修改完后再交給美工,這樣循環(huán)往復,往往要花費大量的時間和精力,如果你所在公司是采取這種模式的話,恐怕老板為了節(jié)省時間,會把很多界面設計也交給程序員來做,畢竟他不會讓你們任何一個閑座著等待.作為程序員的你此時可能會夢想:如果程序員只要負責寫程序代碼,不理會令人煩躁的界面,那就太好了.

          或許Fast Template誕生那刻起(我不敢確定它是最早的PHP模板處理類,但用起來確實很方便),你的夢想就幾近實現.策劃們把東西交給你,當然里面的元素都寫好了的,形如以下tpl.html
          <table border=0 cellspacing=1 cellpadding=2 width=100%>
          ? ? <tr>
          ? ?? ???<td>
          ? ?? ?? ?? ?我愛你{MY_LOVE}
          ? ?? ???</td>
          ? ? </tr>
          </table>
          你只需要在程序里給這些元素(MY_LOVE)賦值就行了tpl.php
          ? ? $tpl->assign("MY_LOVE", "kiki");
          你基本上不用管這些元素的樣式(比如字體,寬度,高度等),所在位置,甚至這些元素將來可能不再使用了.與此同時,美工那邊把元素放進一個HTML頁面里(這個頁面就是我們所說的"模板"),他也不用擔心會不小心把你的程序給搞壞了.然后做完后交給一個專門負責程序和美工結合的人(當然在國內也是程序員做這樣事情),他很可能只需要很小的幾個修改就可以把兩者結合的很好.這樣對你,對美工,都大大提高了工作效率,老板自然也會很高興啦.

          所以我這里所說的"模板"技術,就是可以將程序和美工分離的技術,注意不是邏輯抽象層與表現層的分離.一來,那樣將會讓人不知所云,因為"邏輯抽象"這四個字就已經太抽象了,且表現層并只是美工所做的模板.所以,很多人試圖把Fast Template,PHPLIB Template兩個與Smarty相比較,在我看來,這是明顯不對的.

          PHPLIB Template類也是一個用PHP代碼處理模板的一個類.也是本文要將要闡述的一個模板類.同上面講的一樣,它能把模板中的"元素"替換為你為它設定的值",且處理的很很好,也容易擴展,由于使用了preg_函數,所以速度也比較快.很多人都會提出一個意見:使用模板會讓你的代碼運行的更慢,確實是這樣的,如果你使用嵌入式寫法,會快一些,如果把PHP連同HTML全部寫入PHP里(用 print("<html標簽>"); ),可能會更快.但如果綜合考慮整個項目的開發(fā)效率,以及后期維護性的話,這些代價是可以承受的,而且慢也不會慢哪里去,真正的問題所在可能是你的模板實在是太大了.當然,你也可以改進這個模板類,讓它運行的更快.

          提起PHPLIB Template,很多人自然會聯想起Fast Template來,我也不例外,因為兩者很多地方都很相近.對此,很多人都做了比較,在這里我就不再詳述了,或許王晨的這篇文章值得一看: 在PHP世界中選擇最合適的模板


          獲取

          可以從這里下載 [url]http://www.sanisoft.com/phplib/download.phpPHPLIB[/url] ,然后從壓縮包中php目錄下取出template.inc,就可以供我們使用了.

          文檔

          英文文檔 [url]http://www.sanisoft.com/phplib/manual/template.php[/url]
          我翻譯的中文文檔(僅做參考) [url]http://www.4kiki.net/php_lib_template/[/url]
          還有網上的很多資源,可以通過google搜索得到.

          從類里面注釋可以知道,最新版本是2002/07/11 22:29:51的1.12版,所以,你或許需要修改一些東西,在你懂的前提下.我們還可以下載它的PEAR集成版本([url]http://pear.php.net/package/HTML_Template_PHPLIB/download)[/url] , 不過你的PHP版本需要在4.3.0以上.




          2005-11-8 23:19SOLO
          一個封裝很好的類對使用者(可能不是開發(fā)者本人)來說,最大的好處就是,你無需知道類內部是怎么運作的,只需知道如何利用它提供的接口做你想做的事情即可.所以,本文不打算具體講述PHPLIB Template(以下簡稱Template)是如何將"元素"轉換成"值"的,你需要了解的是"它能這樣做",而不是"它為什么能這樣做".
          好了,下面我們就開始它的第一個應用了.

          先在我們要測試的網站的目錄下建兩個文件夾inc和template.目錄inc下放引用文件,比如類庫,函數庫等,這里我們就把template.inc放如該目錄下.tempate下放模板文件,我們先建一個模板文件first.html,內容如下
          <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
          <HTML>
          <HEAD>
          <TITLE> 我的第一個模板文件 </TITLE>
          </HEAD>

          <BODY>
          真想對你說:我愛你 {lover} ,但我卻不敢說,因為我知道你愛的人是 {man}.
          <P>
          <font color="#0000FF">{author}</font> 于 {date}
          </BODY>
          </HTML>
          用inc,template命名文件目錄,都是我的個人習慣,你完全可以采取不同的方式.我用擴展名為.html的名稱命名模板文件,是為了方便美工用frontpage或者dreamweaver修改,但這完全取決于你自己的習慣.

          first.html模板中的{lover},{man},{author}可以稱為"模板變量",用花括號({})把變量名稱括住即組成一個模板變量.模板變量就是模板元素的一種。你可能會擔心它的命名問題,其實除了空格(" "),回車換行("\r", "\n"),tab(\t)外它都被視為是正確的.所以
          {your-lover}
          也是正確的.這點有時可能會令你很痛苦,因為模板里的有些javascript代碼可能無意間變沒有了,比如
          if(a>b){document.write("i love u");}
          中的
          {document.write("i love u");}
          也被視為一個變量了.上面的代碼在你選的模板處理方式下,可能會變成if(a>b){},從而導致javascript錯誤.為什么會"變沒"了呢?稍后將做解釋.

          上面我們定義的三個變量{lover},{man},{author}的原因是,我們想隨時改變它們的值.下面我們就來做這個工作.新建first.php文件,內容如下:
          <?php
          //包含進模板類 template.inc
          require "inc/template.inc";

          //創(chuàng)建一個實例
          $tpl = new Template("template", "keep"); //注1

          //將整個文件讀進來
          $tpl->set_file("main", "first.html"); //注2

          //給文件中的模板變量賦值
          $tpl->set_var("lover", "kiki"); //注3
          $tpl->set_var("man", "ccterran"); //注4
          $tpl->set_var("author", "iwind"); //注5

          //完成替換
          $tpl->parse("mains", "main"); //注6

          //輸出替換的結果
          $tpl->p("mains"); //注7

          ?>
          瀏覽器中瀏覽這個文件,你就會發(fā)現輸出


          真想對你說:我愛你 kiki ,但我卻不敢說,因為我知道你愛的人是 ccterran.

          iwind 于 {date}


          這一切正如我們所期望的(除了{date}).注1
          $tpl = new Template("template", "keep");
          是創(chuàng)建一個Template類的實例對象.它有兩個參數,都是可選的.

          第一個參數是模板所在目錄,如果不設置則為"."(即當前目錄),由于我們剛才把模板文件first.html放到template下了,所以這里為template.注意它一般使用相對路徑,如果你用相對于根目錄(比如 /phplib/test/template)的路徑,就會出現
          Template Error: set_root: /phplib/test/template is not a directory.
          Halted.
          的錯誤.

          第二個參數是指定模板類對"未完成處理"變量的處理方式,所謂"未完成處理"指的是模板變量未賦值,塊未完成替換工作(下面一節(jié)將講到它),它有三個值可選,分別為"keep","comment","remove":
          如果設為"keep",這些變量將原封不動的保留下來.
          如果設為"comment",那么會在報錯的同時,將未完成處理的變量全部轉換成HTML的注釋.
          如果設為"remove",未完成處理的變量便會被刪除(這也是默認的情況).

          所以在上面的例子中,我指定的是"keep",于是{date}因為未賦值,所以還保留著.而缺省的情況下是"remove",所以,如果我這樣創(chuàng)建實例對象
          $tpl = new Template("template", "remove");
          或者
          $tpl = new Template("template");
          的話,輸出就變成了
          真想對你說:我愛你 kiki ,但我卻不敢說,因為我知道你愛的人是 ccterran.

          iwind 于



          可以看出{date}被刪除了.如果是
          $tpl = new Template("template", "comment");

          它的結果將是


          真想對你說:我愛你 kiki ,但我卻不敢說,因為我知道你愛的人是 ccterran.

          iwind 于


          看起來和"remove"方式一樣,但查看源文件,我們會發(fā)現
          <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
          <HTML>
          <HEAD>
          <TITLE> 我的第一個模板文件 </TITLE>
          </HEAD>

          <BODY>
          真想對你說:我愛你 kiki ,但我卻不敢說,因為我知道你愛的人是 ccterran.
          <P>
          <font color="#0000FF">iwind</font> 于 <!-- Template variable date undefined -->
          </BODY>
          </HTML>

          其中有<!-- Template variable date undefined -->的錯誤信息,告訴我們date變量未定義(賦值).

          用"comment"或許對程序的調試很有幫助.

          我們再回頭看看
          if(a>b){document.write("i love u");}

          {document.write("i love u");}
          會"變沒"的問題,是因為模板類視之為模板變量,但你沒有給它指定值(當然會沒有),且你沒有指定"keep"方式來處理未定義變量,所以它就被"remove"了.

          所以在模板使用過程中應該多多注意這些問題.

          注2是將一個模板文件加載進來,事實上你可以一次加載多個模板(在第四節(jié)將講到這個問題).你可以想象
          $tpl->set_file("main", "first.html");
          把"first.html"內容給變量"main"(盡管很多人稱之為"句柄",但本文決定不談"句柄"),所以"main"的值就變成模板的內容了,包含著那些模板變量.

          注3,注4,注5,是給模板變量賦值.值是什么,你自然可以隨便定.比如你還可以
          $tpl->set_var("lover", "kiki1");
          $tpl->set_var("man", "ccterran1");
          $tpl->set_var("author", "iwind_php");
          你也可以一次完成給一列的變量賦值.這樣
          $tpl->set_var(
          array("lover"=>"kiki", "man"=>"ccterran", "author"=>"iwind")
          );
          如果你想設置一個變量的值為空的話,可以
          $tpl->set_var("man", "");
          或者
          $tpl->set_var("man");

          注6,是執(zhí)行將上面$tpl->set_var給模板變量指定的值替換掉模板中的模板變量這個操作,第一個參數即為模板分析的結果,也可以視為一個變量.

          當然注7的 $tpl->p("mains"); 就將模板分析的結果如你所愿的輸出啦.

          喏,恭喜你,你的第一個模板類應用就完成了.你可能不小心弄錯了哪個地方,模板類默認情況下會自動打印出錯誤提示的,根據這些提示,你就很容易就可以找出問題所在,在第6節(jié)將會具體講到.


          SOLO
          PHPLIB Template入門系列 - 3 塊的應用
          在上一節(jié)中,我們知道模板元素的一種:模板變量,并知道如何在程序中給它賦值,使之呈現我們想要的東西.這對一般的簡單網頁來說,或許就已經夠用了.現在我們設想一稍微復雜的一種情況,在template目錄下新建一個second.html模板文件,內容為:
          <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
          <HTML>
          <HEAD>
          <TITLE> 我的第二個模板文件 </TITLE>
          </HEAD> <BODY>
          下面是一個列表
          <UL>
          <li>張三 的成績是 82
          <li>李四 的成績是 90
          <li>王兒 的成績是 60
          <li>麻子 的成績是 77
          </UL>
          </BODY>
          </HTML>
          上面的列表中列出了"張三","李四","王二","麻子"四人的成績.假設要用PHP代碼嵌入HTML的方式輸出的話,你可能是這樣寫的:
          <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
          <HTML>
          <HEAD>
          <TITLE> 我的第二個模板文件 </TITLE>
          </HEAD>

          <BODY>
          下面是一個列表
          <?php
          $result = mysql_query("SELECT username,score FROM my_tbl");
          ?>
          <UL>
          <?php
          while ($row = mysql_fetch_array($result))
          {
          ?>
          <li><?=$row["username"]?> 的成績是 <?=$row["score"]?>
          <?php
          }
          ?>
          </UL>
          </BODY>
          </HTML>

          這樣寫很適合PHP新手,但你很快發(fā)現你或者美工改這個列表樣式的時候需要多么的小心翼翼,特別是美工,如果他不懂你寫得PHP代碼,那么他會終日生在恐懼之中!因為稍微的不小心,可能就會帶來程序的運行錯誤.而且如果他想把這個列表從一個地方移到另一個地方,也是相當不容易的.于是作為程序員的你不得不把美工(雖然你做的可能性更大)修飾過的頁面重新審查一次,無形中就造成費時費力。

          現在好了,有了Template模板類,你可以把你的代碼從模板中抽取出來了.你可能會這樣修改second.html模板:
          <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
          <HTML>
          <HEAD>
          <TITLE> 我的第二個模板文件 </TITLE>
          </HEAD>

          <BODY>
          下面是一個列表
          <UL>
          <li>{username1} 的成績是 {score1}
          <li>{username2} 的成績是 {score2}
          <li>{username3} 的成績是 {score3}
          <li>{username4} 的成績是 {score4}
          </UL>
          </BODY>
          </HTML>

          顯然,你采取了一個良好的命名方式,用1,2,3..來表示每一行數據,然后你在你的程序里循環(huán)給這些變量賦值,也是不難的,比如:(second.php)

          <?php
          //包含進模板類 template.inc
          require "inc/template.inc";

          //創(chuàng)建一個實例
          $tpl = new Template("template");

          //將整個文件讀進來
          $tpl->set_file("main", "first.html");

          //連接數據庫,選擇數據庫略
          省略.....

          //查詢結果
          $result = mysql_query("SELECT username,score FROM my_tbl");

          //給文件中的模板變量賦值
          $i=0;
          while ($row = $idb->fetch_array($result))
          {
          $i++;
          $tpl->set_var("username" . $i, $row["username"]);
          $tpl->set_var("score" . $i, $row["score"]);
          }

          //完成替換
          $tpl->parse("mains", "main");

          //輸出
          $tpl->pparse("mains", "main");

          ?>

          這樣你也能得到正確結果.在特殊情況下你或許需要這樣做.但Template提供了一個更方便的"大的模板變量",那就是塊.我之所以稱之為"大的模板變量",是因為它也可以視為可以包含其他模板變量的變量.形式如
          <UL>
          <!-- BEGIN list -->
          <li>{username} 的成績是 {score}
          <!-- END list -->
          </UL>

          即用<!-- BEGIN 塊名稱 -->和<!-- END 塊名稱 -->定義了一個名為list的塊,(注意:我在這里為了方便理解,只稱之為塊名稱).這個塊里面又包含一些HTML代碼(<li>等等)以及模板變量({username},{score}).

          在講述如何用塊輸出列表之前,我們先談一下塊的定義格式.

          首先<!-- BEGIN list -->和<!-- END list --> 都要各自為一行,亦即下面的塊的定義是錯誤的
          1,
          同行的 <!-- BEGIN list -->
          <li>{username} 的成績是 {score}
          <!-- END list -->
          2,
          <!-- BEGIN list -->
          <li>{username} 的成績是 {score}
          <!-- END list --> 同行的

          <!--和-->都是固定的,也就是說只能是兩個中劃線("-"),且它們與BEGIN list之間都至少有一個空(空格或tab),看下面的例子
          <!--BEGIN list -->
          <!-- BEGIN list-->
          它們都是錯誤的塊的定義方法,因為第一個<!--與BEGIN之間至少應該有一個空,第二個-->與list之間至少有一個空.

          BEGIN/END和list之間也應該有一個空格,注意是有且僅有一個空格,不能多也不能少.

          塊的名稱建議你只使用字符,數字,下劃線以及它們的組合.

          BEGIN和END兩個詞語都應該是大寫的。

          好了,下面開始探討如何是這個塊變成一個列表.我們可以這樣
          <?php
          //包含進模板類 template.inc
          require "inc/template.inc";

          //創(chuàng)建一個實例
          $tpl = new Template("template");

          //將整個文件讀進來
          $tpl->set_file("main", "second.html");

          //加載塊list
          $tpl->set_block("main", "list", "lists");

          //連接數據庫,選擇數據庫略
          省略.....

          //查詢結果
          $result = mysql_query("SELECT username,score FROM my_tbl");

          //給文件中的模板變量賦值
          while ($row = $idb->fetch_array($result))
          {
          $tpl->set_var("username", $row["username"]);
          $tpl->set_var("score", $row["score"]);
          $tpl->parse("lists", "list", true);
          }

          //完成替換
          $tpl->parse("mains", "main");

          //輸出
          $tpl->pparse("mains", "main");

          ?>

          記住把你的數據庫連接寫在我省略的部分,就可以打印正確的結果,一如

          下面是一個列表

          張三 的成績是 82
          李四 的成績是 90
          王兒 的成績是 60
          麻子 的成績是 77



          可以看到在PHP代碼里有兩個東西
          $tpl->set_block("main", "list", "lists"); //代碼1
          $tpl->parse("lists", "list", true);
          就不可思議的將整個塊循環(huán)輸出了.代碼1用來加載模板main中的塊list,并給其一個名字lists,list就是模板中的一個大變量,它的內容就是<li>{username} 的成績是 {score}即:
          "list" = "<li>{username} 的成績是 {score}"
          之所以用lists命名,是為了程序的可讀性,也就是說我很容易就知道XXXs是XXX塊的名稱.

          使用set_block后,模板中的塊內容
          <!-- BEGIN list -->
          <li>{username} 的成績是 {score}
          <!-- END list -->
          就被lists代替了.于是我們的模板就變成了
          <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
          <HTML>
          <HEAD>
          <TITLE> 我的第二個模板文件 </TITLE>
          </HEAD>

          <BODY>
          下面是一個列表
          <UL>
          {lists}
          </UL>
          </BODY>
          </HTML>

          塊變成了一個變量(lists)!下面只要將lists變量替換成我們想要的就行了.

          代碼二所處的循環(huán)
          while ($row = $idb->fetch_array($result))
          {
          $tpl->set_var("username", $row["username"]);
          $tpl->set_var("score", $row["score"]);
          $tpl->parse("lists", "list", true); //代碼2
          }
          每一次循環(huán),兩個set_var分別給username,score賦值,然后"list"就變成了
          "list" = "<li>具體的名字 的成績是 具體的分數"
          代碼2就是將list分析后的內容賦給lists,這樣就完成了整個塊的分析.

          parse第三個參數可以設置list中的值是直接存在lists里面,還是附加在原有值之后.我們這里設置為true,說明是附加在原有值之后,才得以每個list的值都會顯示出來.反之設為false的話,后面的值會覆蓋掉以前的值.最終的結果會是


          下面是一個列表

          麻子 的成績是 77


          綜上所述,Template模板類的替換方式是:
          1,用set_block將模板中的list塊(或者你命名的其他塊)替換成變量lists.
          2,用set_var給list塊中的變量賦值
          3,把賦值并執(zhí)行替換后的list內容依次給lists
          4,完成分析

          2005-11-8 23:20SOLO
          在PHP程序里,我們常常會把"公用代碼"或"公用部分"寫進一個文件里,前者象我們的系統(tǒng)配置文件,比如config.php,或者公共函數都寫入一個functions.php文件里;后者象一個站點都需要用到的頁面頭部,尾部.這樣做的好處是可以很方便的維護站點,而如果這個公用部分要有所改動,無需再去改每一個頁面,大大減少了我們的工作量.
          以前你或許用require,include(require_once,include_once)引進一個公用的頁面頭部,確實方便而有效,現在我們用Template模板類也可以實現了,并且可以很方便的把一個頁面隨意插入另一個模板的任意地方.如果你想也把要插進的頁面做成含有變量的模板的話,那么你會發(fā)現模板類會把這個工作處理的很好.

          在template目錄下新建三個文件third.html,header.html,footer.html.內容分為如下
          third.html
          <!-- 這是頁面頭部 -->
          {header}
          <BODY>
          下面是一個列表
          <UL>
          <!-- BEGIN list -->
          <li>{username} 的成績是 {score}
          <!-- END list -->
          </UL>
          <!-- 這是頁面腳部 -->
          {footer}
          </BODY>
          </HTML>

          header.html
          <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
          <HTML>
          <HEAD>
          <TITLE> {title} </TITLE>
          </HEAD>

          footer.html
          <P>author &copy; iwind

          你也看到了,我們前幾節(jié)的例子中都是用
          $tpl->set_file("main", "模板文件名");
          來加載模板文件的。只所以命名為"main",是因為我們想給它一個意義:主模板。這里的third.html就可以稱之為“主模板”,而欲嵌入主模板third.html的{header}變量所在位置的模板文件header.html,則可以稱為"子模板".同樣footer.html也是一個"子模板",我們想把它放到主模板里的{footer}位置.一個主模板內可以隨意嵌入不限內容,尺寸大小,格式等的任何多個子模板.

          下面我們開始我們的PHP程序.

          先是創(chuàng)建一個類的實例對象
          //包含進模板類 template.inc
          require "inc/template.inc";

          //創(chuàng)建一個實例
          $tpl = new Template("template");

          //讀進三個模板文件的內容,分別給變量"main", "my_header", "my_footer"
          $tpl->set_file("main", "third.html");
          $tpl->set_file("my_header", "header.html");
          $tpl->set_file("my_footer", "footer.html");

          //執(zhí)行my_header,my_footer里的模板變量替換,并把最終結果分別賦給主模板中的header,footer
          $tpl->parse("header", "my_header");
          $tpl->parse("footer", "my_footer");

          //然后完成主模板內變量的替換,并輸出主模板分析后的內容
          $tpl->parse("mains", "main");

          //輸出
          $tpl->p("mains");

          于是,我們便可以通過查看源文件確信header.html,footer.html兩個子模板文件的內容已經被加進主模板里了.

          <!-- 這是頁面頭部 -->
          <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
          <HTML>
          <HEAD>
          <TITLE> </TITLE>
          </HEAD>
          <BODY>
          下面是一個列表
          <UL>
          <!-- BEGIN list -->
          <li> 的成績是
          <!-- END list -->
          </UL>
          <!-- 這是頁面腳部 -->
          <P>author &copy; iwind
          </BODY>
          </HTML>

          你會發(fā)現,所有的變量都沒了,包括我們未賦值的{title},{username},{score}.這是因為我們在創(chuàng)建對象時,第二個參數未設置,而自動采用了"remove"
          $tpl = new Template("template");

          $tpl = new Template("template", "remove");
          的效果是一樣的.

          如果我們想給這些變量也賦值,那么方法和單個模板里變量的分析方法是一樣的.
          //讀模板內容進變量
          $tpl->set_file("main", "third.html");
          $tpl->set_file("my_header", "header.html");
          $tpl->set_file("my_footer", "footer.html");

          //設置子模板header.html里的變量title的值
          $tpl->set_var("title", "這個是網頁標題");

          //以下分析主模板里的塊的內容
          //設置塊
          $tpl->set_block("main", "list", "lists");
          $array = array("張三" => 82, "李四" => 90, "王二" => 60, "麻子" => 77);
          foreach ($array as $username=>$score)
          {
          ? ? $tpl->set_var("username", $username);
          ? ? $tpl->set_var("score", $score);
          ? ? $tpl->parse("lists", "list", true);
          }

          所有程序為
          <?php
          //包含進模板類 template.inc
          require "inc/template.inc";

          //創(chuàng)建一個實例
          $tpl = new Template("template");

          //將整個文件讀進來
          $tpl->set_file("main", "third.html");
          $tpl->set_file("my_header", "header.html");
          $tpl->set_file("my_footer", "footer.html");

          //設置header.html里的變量title的值
          $tpl->set_var("title", "這個是網頁標題");

          //設置塊
          $tpl->set_block("main", "list", "lists");
          $array = array("張三" => 82, "李四" => 90, "王二" => 60, "麻子" => 77);
          foreach ($array as $username=>$score)
          {
          $tpl->set_var("username", $username);
          $tpl->set_var("score", $score);
          $tpl->parse("lists", "list", true);
          }

          //執(zhí)行my_header,my_footer里的模板變量替換,并把最終結果分別賦給主模板中的header,footer
          $tpl->parse("header", "my_header");
          $tpl->parse("footer", "my_footer");

          //完成主模板內變量的替換
          $tpl->parse("mains", "main");

          //輸出
          $tpl->p("mains");

          ?>

          輸出的結果為
          <!-- 這是頁面頭部 -->
          <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
          <HTML>
          <HEAD>
          <TITLE> 這個是網頁標題 </TITLE>
          </HEAD>
          <BODY>
          下面是一個列表
          <UL>

          <li>張三 的成績是 82
          <li>李四 的成績是 90
          <li>王二 的成績是 60
          <li>麻子 的成績是 77
          </UL>
          <!-- 這是頁面腳部 -->
          <P>author &copy; iwind
          </BODY>
          </HTML>

          一切都是我們所期望的.

          在這個程序里,我們用
          $tpl->set_block("main", "list", "lists");
          加載一個塊.其實它的第一個參數為該塊所在父變量,如果這個塊在header.html里,那么恐怕要這樣寫了
          $tpl->set_block("my_header", "list", "lists");
          但分析方法還是一樣的.

          從以往和這節(jié)中的例子,我們可以看出來,定義一個模板變量{var}值的方法是用
          $tpl->set_var("var_name", "var_value");
          但把一個變量的值給另一個變量就需要用parse.
          $tpl->parse("target_name", "from_name", true);
          或者
          $tpl->parse("target_name", "from_name", false);
          使用parse就先執(zhí)行from_name大變量的模板變量的替換,然后再把所得結果賦給target_name.

          一個變量{varname}無論在模板的何處(塊里面,子模板里),定義的方法都是一樣的.

          子模板里還可以嵌入新的子模板,稱之為"多重嵌套",分析的方法都是一樣的,只是一般用不到.塊也可以多重嵌套,而且非常有用,使得模板可以設計的可以很清晰,這就是我們下一節(jié)的內容了.
          posted on 2006-08-10 12:17 jackstudio 閱讀(615) 評論(0)  編輯  收藏 所屬分類: php
          主站蜘蛛池模板: 行唐县| 黎川县| 六安市| 旺苍县| 大冶市| 宜兴市| 邹城市| 嘉义市| 深泽县| 化德县| 伊金霍洛旗| 临江市| 克什克腾旗| 洪江市| 梁山县| 安新县| 温泉县| 博乐市| 绥宁县| 潞城市| 宝鸡市| 汝阳县| 定襄县| 普宁市| 松江区| 酒泉市| 丰县| 于田县| 聊城市| 道孚县| 尖扎县| 宁波市| 邵东县| 彭山县| 泾阳县| 盐源县| 万源市| 饶平县| 洞口县| 长乐市| 明水县|