PHP模板解析類別
-
- class template {
- private $vars = array();
- private $conf = '';
- private $tpl_name = 'index';//如果模板不存在會查找當前controller預設index模板
- private $tpl_suffix = '.html';//如果CONFIG沒配置預設後綴則顯示
- private $tpl_compile_suffix = '.tpl.php';//編譯模板路徑
- private $template_tag_left = ' private $template_tag_right = '}>';//模板右標籤
- private $template_c = '';//編譯目錄
- private $template_path = '';//模板完整路徑
- private $template_name = '';//模板名稱index.html
-
-
- //定義每個模板的標籤的元素
- private $tag_foreach = array('from', 'item', 'key');
- private $tag_include = array('file');//目前只支援讀取模板預設路徑
-
- public function __construct($conf) {
- $this->conf = &$conf;
-
- $this->template_c = $this- >conf['template_config']['template_c'];//編譯目錄
- $this->_tpl_suffix = $this->tpl_suffix();
- }
-
-
-
- private function str_replace($search, $replace, $content) {
- if(empty($search) || empty($replace) || empty($content)) return false;
- return str_replace($search , $replace, $content);
- }
-
- /**
- * preg_match_all
- * @param $pattern 正規
- * @param $content 內容
- * @return array
- */
-
- private function preg_match_all($pattern, $content) {
- if(empty( $pattern) || empty($content)) core::show_error('查找模板標籤失敗!');
- preg_match_all("/".$this->template_tag_left.$pattern.$this->template_tag_right." /is", $content, $match);
- return $match;
- }
- /**
- * 範本檔案後綴
- */
- public function tpl_suffix() {
- $tpl_suffix = empty( $this->conf['template_config']['template_suffix']) ?
- $this->tpl_suffix :
- $this->conf['template_config']['template_suffix'] ;
- return $'template_config']['template_suffix'] ;
- return $ tpl_suffix;
- }
-
- /**
- * 此處不解釋了
- * @return
- */
- public function assign($key, $value) {
- $this->vars[$key] = $value;
- }
-
- /**
- * 渲染頁面
- * @param
- * 使用方法1
- * $this->view->display('error', 'comm/');
- * 預設是指向TPL模版的跟目錄,所以comm/就是tpl/comm/error.html
- * 使用方法2
- * $this->view->display('errorfile');
- * 預設指向控制器固定的資料夾
- * 例如你的網域是http://heartphp/admin/index, 那麼正確路徑就是tpl/admin/index/errorfile.html
- * @return
- */
- public function display($filename = '', $view_path = '') {
- $tpl_path_arr = $this->get_tpl( $filename, $view_path);//取得TPL完整路徑並且向指標傳送路徑以及名稱
- if(!$tpl_path_arr) core::show_error($filename.$this->_tpl_suffix.'模板不存在');
-
- //編譯開始
- $this->view_path_param = $view_path;//使用者傳遞過來的模版跟目錄
- $this->compile();
-
- }
-
- /**
- * 編譯控制器
- * @param
- * @return
- */
- private function compile() {
- $filepath = $this->template_this.$this->template_name;
- $compile_dirpath = $path.> check_temp_compile();
- $vars_template_c_name = str_replace($this->_tpl_suffix, '', $this->template_name);
-
-
- $include_name = $this-this-_replace( read_file($filepath), $compile_dirpath, $vars_template_c_name);//解析
- if($include_file) {
- $this->read_config() && $config = $this->read_config();
- extract($this->vars, EXTR_SKIP);
- [url=home.php?mod=space&uid=48608]@include[/url] $include_file;
- }
- }
-
-
- /**
- * 讀取目前專案設定檔
- */
- protected function read_config() {
- if(file_exists(SYSTEM_PATH.'conf/config.php')) {
- @include SYSTEM_PATH.'conf/config.php')) {
- @include SYSTEM_PATH.'conf/config.php')) {
- @include SYSTEM_PATH.'conf/config.php' ;
- return $config; } return false; }
- /**
- * 구문 분석 템플릿 구문
- * @param $str 콘텐츠
- * @param $compile_dirpath 템플릿 컴파일 디렉터리
- * @param $vars_template_c_name 템플릿 컴파일 파일 이름
- * @return 컴파일된 PHP 템플릿 파일 이름
- */
- 비공개 함수 template_replace($str, $compile_dirpath, $vars_template_c_name) {
- if(empty($str)) core::show_error('템플릿 내용이 비어 있습니다. !');
-
- //컴파일 헤더 처리
- $compile_path = $compile_dirpath.$vars_template_c_name.$this->tpl_compile_suffix;//파일 컴파일
-
- if(is_file($compile_path )) {
- //$header_content = $this->get_compile_header($compile_path);
- //$compile_date = $this->get_compile_header_comment($header_content);
-
- $tpl_filemtime = filemtime($this->template_path.$this->template_name);
- $compile_filemtime = filemtime($compile_path);
-
- //echo $tpl_filemtime.'=='.date('Y-m-d H:i:s', $tpl_filemtime).'
';
- //echo $compile_filemtime.'=='.date('Y-m-d H:i:s', $compile_filemtime);
- //파일이 만료된 경우 템플릿 태그에 include가 있고 수정되면 다시 컴파일합니다.
- //<{include file="public/left.html"}> DEBUG가 아닙니다. 모드에서 메인 파일을 변경하지 않으면 현재 include에 있는 파일이 다시 컴파일되지 않습니다. 저도 변경할지 고민 중인데 아직 생각해본 적은 없습니다. 당분간은 개발 단계에서 DEBUG=1 모드를 켜야 합니다. 그렇지 않으면 포함 파일 수정이 무효화됩니다.有點囉嗦,不知道表達清楚沒
- if($tpl_filemtime > $compile_filemtime || DEBUG) {
- $ret_file = $this->compile_file($vars_template_c_name, $str, $compile_dirpathpath); else {
- $ret_file = $compile_path;
- }
- } else {//編譯檔不存在建立他
- $ret_file = $this->compile_file($vars_template_c_name, $str, $compile_dir, $compile_dir) ;
- }
-
- return $ret_file;
- }
-
-
- /**
- * 範本檔案主體
- * @param string $str 內容
- * @return html
- */
- private function body_content($str) {
- //解析
- $str = $this->parse($str);
-
- $header_comment = "Create On##".time()."|Compiled from##".$this- >template_path.$this->template_name;
- $content = " if(!defined('IS_HEARTPHP')) exit('Access Denied');/*{$header_comment}*/?>rn$str" ;
-
- return $content;
- }
-
- /**
- * 開始解析相關範本標籤
- * @param $content 範本內容
- */
- private function parse($content) {
- //foreach
- $ content = $this->parse_foreach($content);
-
- //include
- $content = $this->parse_include($content);
-
- //if
- $ content = $this->parse_if($content);
-
- //elseif
- $content = $this->parse_elseif($content);
-
- //範本標籤公用部分
- $content = $this->parse_comm($content);
-
- //轉為php程式碼
- $content = $this->parse_php($content);
- return $content;
- }
-
- /**
- * echo 如果預設直接 轉成
- */
- private function parse_echo($content) {
-
- }
-
- /**
- /**
- * 轉換為PHP
- * @param $content html 範本內容
- * @return html 取代好的HTML
- */
- private function parse_php($content){
- if(empty($content)) return false;
- $content = preg_replace("/".$this->template_tag_left."(. ?)". $this->template_tag_right."/is", "", $content);
-
- return $content;
- }
- /**
- * if判斷語句
- *
- * zhang
- *
- * liang
- *
- * 張亮
- *
- */
- private function parse_if($content) {
- if(empty($content)) return false;
- //preg_match_all("/".$this->template_tag_left."ifs (.*?)". $this->template_tag_right."/is", $content, $match);
-
- $match = $this->preg_match_all("ifs (.*?)", $content);
- if (!isset($match[1]) || !is_array($match[1])) return $content;
-
- foreach($match[1] as $k => $v) {
- //$s = preg_split("/s /is", $v);
- //$s = array_filter($s);
- $content = str_replace($match[0][$k] , "", $content);
- }
-
- return $content;
- }
-
- private function parse_elseif($ content) {
- if(empty($content)) return false;
- //preg_match_all("/".$this->template_tag_left."elseifs (.*?)".$this->template_tag_right." /is", $content, $match);
- $match = $this->preg_match_all("elseifs (.*?)", $content);
- if(!isset($match[1]) || !is_array($match[1])) return $content;
-
- foreach($match[1] as $k => $v) {
- //$s = preg_split("/ s /is", $v);
- //$s = array_filter($s);
- $content = str_replace($match[0][$k], "", $content);
- }
-
- return $content;
- }
- /**
- * 解析include include標籤不是即時更新的當主體檔案更新的時候才更新標籤內容,所以想include生效請修改一下主體檔案
- * 記錄一下有時間開發一個當DEBUG模式的時候每次執行刪除模版編譯檔案
- * 使用方法
- * @param $content 範本內容
- * @return html
- */
- private function parse_include($content) {
- if(empty($content)) return false;
-
- //preg_match_all("/".$this->template_tag_left."includes (.*?)".$this->template_tag_right."/is", $content, $match);
- $match = $this->preg_match_all("includes (.*?)", $content);
- if(!isset($match[1]) || !is_array($match[1])) return $content;
-
- foreach($match[1] as $match_key => $match_value) {
- $a = preg_split("/s /is", $match_value);
-
- $new_tag = $new_tag array();
- // 分析元素
- foreach($a as $t) {
- $b =explode('=', $t);
- if(in_array ($b[0 ], $this->tag_include)) {
- if(!empty($b[1])) {
- $new_tag[$b[0]] = str_replace(""" , "", $b [1]);
- } else {
- core::show_error('模板路徑不存在!');
- }
- }
- }
-
- extract($new_tag );
- // 查詢範本檔案
- foreach($this->conf['view_path'] as $v){
- $conf_view_tpl = $v.$file;/ /include 範本檔案
- if(is_file($conf_view_tpl)) {
- $c = $this->read_file($conf_view_tpl);
-
-
- $inc_file = str_replace($this- >_tpl_suffix, '', name($this-d $file));
-
- $this->view_path_param = dirname($file).'/';
- $compile_dirpath = $this->check_temp_compile( );
-
- $include. $this->template_replace($c, $compile_dirpath, $inc_file);//解析
-
- break;
- } else {
- core: :show_error('模板檔案不存在,請仔細檢查檔案:'. $conf_view_tpl);
- }
- }
-
- $content = str_replace($match[0][$match_key], '', $content);
- }
-
- return $content;
-
- }
- /**
- * 解析foreach
- * 使用方法
- * @param $content 模板內容
- * @return html 解析後的內容
- */
- 私有函數parse_foreach($ content) {
- if(empty($content)) return false;
-
- //preg_match_all("/".$this->template_tag_left."foreachs (.*?)".$this-> ; template_tag_right."/is", $content, $match);
- $match = $this->preg_match_all("foreachs (.*?)", $content);
- if(!isset($match ) [1]) || !is_array($match[1])) return $content;
-
- foreach($match[1] as $match_key => $value) {
-
- $ split = preg_split("/s /is", $value);
- $split = array_filter($split);
-
- $new_tag = array();
- foreach($split as $v ) {
- $a =explode("=", $v);
- if(in_array($a[0], $this->tag_foreach)) {//此處過濾標籤不存在過濾
- $new_tag[$a[0]] = $a[1];
- }
- }
- $key = '';
-
- extract($new_tag);
- $鍵=($鍵)? '$'.$鍵。 ' =>' : '' ;
- $s = '';
- $ content = $this->str_replace($match[0][$match_key], $s, $content);
-
- }
-
- return $content;
- }
-
- /**
- * 匹配結束 字串
- */
- 私人函數parse_comm($content) {
- $search = array(
- "/".$this->template_tag_left."/foreach".$this- >template_tag_right."/is",
- "/".$this->template_tag_left."/if".$this->template_tag_right."/is",
- "/".$this- >template_tag_left. "else".$this->template_tag_right."/is",
-
- );
-
- $replace = array(
- " ;",
- "",
- ""
- );
- $content = preg_replace($search, $replace , $content);
- 回傳$ content;
- }
- /**
- * 檢查編譯目錄 如果沒有建立 則遞歸建立目錄
- * @param string $path 檔案完整路徑
- * @return 範本內容
- */
- private function check_temp_compile() {
- //$paht = $this->template_c.
-
- $tpl_path = ($this->;路徑參數)? $this->view_path_param : $this->get_tpl_path() ;
- $all_tpl_apth = $this->template_c.$tpl_path;
-
- if(!is_dir($all_tpl_apth)) >> ->create_dir($tpl_path);
- }
-
- return $all_tpl_apth;
- }
- /**
- * 讀取檔案
- * @param string $path 檔案完整路徑
- * @return 範本內容
- */
- private function read //$this->check_file_limits($path, 'r');
-
- if(($r = @fopen($path, 'r')) === false) {
- core ::show_error('模版檔案沒有讀取或執行權限,請檢查!');
- }
- $content = fread($r, filesize($path));
- fclose($r) ;
- return $content;
- }
-
- /**
- * 寫入檔案
- * @param string $filename 檔案名稱
- * @param string $content 範本內容
- * @return 檔案名稱
- */
- 私人函數compile_file($filename, $content, $dir) {
- if(empty( $filename)) core::show_error("{$filename} 建立失敗");
-
- $content = $this->body_content($content);//對檔案內容運算
- //echo '開始編譯了=====';
- $f = $dir.$filename.$this->tpl_compile_suffix;
-
- //$this->check_file_limits ($f, 'w') ;
- if(($fp = @fopen($f, 'wb')) === false) {
- core::show_error($f.'
編譯文件失敗,請檢查文件權限。 ($fp, LOCK_UN LOCK_NB);
- fclose($fp);
-
- return $f;
- }
-
- /**
- * 這個檢查檔案權限函數 暫時廢棄了
- * @param [$path] [路徑]
- * @param [status] [w=write, r=read]
- */
- check_file_limits($path , $status = 'rw') {
- clearstatcache();
- if(!is_writable($path) && $status == 'w') {
- core::show_error(" {$path}
沒有寫入權限,請檢查。 ");
- } elseif(!is_read($path) && $status == 'r ') {
- core::show_error("{$path}
沒有讀取權限,請檢查。 ");
- } elseif($status == 'rw') {//檢查寫入並讀取
- if(!is_writable($path) || !is_read($path)) {
- core::show_error("{$path}
>沒有讀取或讀取權限,請檢查");
- }
- }
-
-
- }
-
- /**
- * 讀取編譯後範本的第一行並分析成陣列
- * @param string $filepath 檔案路徑
- * @param number $line 行數
- * @return 傳回指定行數的字串
- */
- /*
- 私有函數get_compile_header($filepath, $line = 0) {
-
- if (($file_arr = @file($filepath)) === false) {
- core::show_error($filepath.'
>讀取檔案失敗,請檢查檔案權限!');
- }
- return $file_arr[0];
- }
- */
-
- /**
- * 分析頭部註解的日期
- * @param string $cotnent 編譯檔案頭部第一行
- * @return 回傳上一次日期
- */
- /*
- private function get_compile_header_comment($content) {
- preg_match("//*(.*?)*//", $content, $match);
- if(!isset($match[1]) || empty( $match[1])) core::show_error('編譯錯誤!');
- $arr = explode('|', $match[1]);
- $arr_date = explode('##' , $arr[0]);
-
- return $arr_date[1];
- }
- */
- /**
- * 取得範本完整路徑 並傳回已存在檔案
- * @param string $filename 檔案名稱
- * @param string $view_path 範本路徑
- * @return
- */
- private function get_tpl($filename , $view_path) {
- empty($filename) && $filename = $this->tpl_name;
-
- //遍歷範本路徑
- foreach($this->conf['view_path'] as $path) {
- if($view_path) {//直接從tpl跟目錄找檔案
- $tpl_path = $path.$view_path;
- $view_file_path = $tpl_path.$filename.$this-> _tpl_suffix;
- } else {//根據目錄,控制器,方法開始找檔案
- $view_file_path = ($tpl_path = $this->get_tpl_path($path)) ? $tpl_path.$filename.$this- >_tpl_suffix : exit(0);
- }
-
- if(is_file($view_file_path)) {
- //傳送模板路徑和模板名稱給指標tpl_path;//
- $this->template_name = $filename.$this->_tpl_suffix;
- return true;
- } else {
- core::show_error($filename.$this->_tpl_suffix .'模板不存在');
- }
- }
- }
-
- /**
- * 取得範本路徑
- * @param string $path 主目錄
- * @return URL D和M的拼接路徑
- */
- private function get_tpl_path($path = '') {
- core::get_directory_name() && $path_arr[0] = core::get_directory_name();
- core::get_controller_name() && $path_arr[1] = core::get_controller_name();
- (is_array( $path_arr)) ? $newpath = implode('/', $path_arr) : core::show_error('取得範本路徑失敗!') ;
-
- return $path.$newpath.'/';
- }
-
- /**
- * 建立目錄
- * @param string $path 目錄
- * @return
- */
- private function create_dir($path, $mode = 0777){
- if(is_dir($path)) return false> $dir_arr = explode('/', $path);
- $dir_arr = array_filter($dir_arr);
-
- $allpath = '';
- $newdir = $this-this> template_c;
-
- foreach($dir_arr as $dir) {
- $allpath = $newdir.'/'.$dir;
-
- if(!is_dir($allpath)) {
-
- if(!is_dir($allpath)) {
- $newdir = $allpath;
-
- if(!@mkdir($allpath, $mode)) {
- core::show_error( $allpath.'
建立目錄失敗,請檢查是否有可都寫權限! ');
- }
- chmod($allpath, $mode);
- }
- chmod($allpath, $mode);
- } else {
- $newdir = $allpath;
- }
- }
- return true;
- }
- }
- return true;
- }
-
- public function __destruct(){
$this->vars = null; $this->view_path_param = null; } }; | };
};