PHPテンプレート解析クラス

WBOY
WBOYオリジナル
2016-07-25 08:50:461186ブラウズ
PHPテンプレート解析クラス
  1. class template {
  2. private $vars = array();
  3. private $conf = '';
  4. private $tpl_name = 'index';// テンプレートが存在しない場合、現在のコントローラーが検索されます デフォルトのインデックス テンプレート
  5. private $tpl_suffix = '.html';//CONFIG がデフォルトのサフィックスで構成されていない場合、それが表示されます
  6. private $tpl_compile_suffix= '.tpl.php';//テンプレートをコンパイルしますpath
  7. private $template_tag_left = '<{' ;//テンプレート左タグ
  8. private $template_tag_right = '}>';//テンプレート右タグ
  9. private $template_c = '';//コンパイルディレクトリ
  10. private $template_path = '';//テンプレートのフルパス
  11. private $ template_name = '';//テンプレート名index.html
  12. //各テンプレートのタグを定義する要素
  13. private $tag_foreach = array('from', 'item' , 'key');
  14. private $tag_include = array('file');//現在、テンプレートのデフォルト パスの読み取りのみをサポートしています
  15. public function __construct($conf) {
  16. $this->conf = &$ conf;
  17. $this->template_c = $this ->conf['template_config']['template_c'];//コンパイルディレクトリ
  18. $this->_tpl_suffix = $this->tpl_suffix();
  19. }
  20. プライベート関数 str_replace($search, $ replace, $content) {
  21. if(empty($search) || empty($replace) || empty($content)) return false;
  22. return str_replace($ search, $replace, $content);
  23. }
  24. /**
  25. * preg_match_all
  26. * @param $pattern Regular
  27. * @param $content コンテンツ
  28. * @return array
  29. */
  30. プライベート関数 preg_match_all($pattern, $content) {
  31. if(empty($pattern) || empty($content)) core::show_error('テンプレート タグが見つかりませんでした!') ;
  32. preg_match_all("/".$this->template_tag_left.$pattern.$this->template_tag_right."/is", $content, $match) ;
  33. return $match;
  34. }
  35. /**
  36. * テンプレートファイルのサフィックス
  37. */
  38. public function tpl_suffix() {
  39. $tpl_suffix = empty($this->conf['template_config']['template_suffix'])
  40. $ this->tpl_suffix :
  41. $this->conf[ 'template_config']['template_suffix'] ;
  42. return $tpl_suffix;
  43. }
  44. /**
  45. * ここでは説明はありません
  46. * @return
  47. */
  48. public function assign($key, $ value) {
  49. $this->vars[$key] = $value;
  50. }
  51. /**
  52. * ページをレンダリングします
  53. * @param
  54. * 使用方法 1
  55. * $this->view->display('error', 'comm/');
  56. * デフォルトでは、TPL の次のディレクトリを指しますテンプレートなので comm/ tpl/comm/error.html です
  57. * 使用方法 2
  58. * $this->view->display('errorfile'); * デフォルトでは、コントローラー
  59. * たとえば、ドメイン名が http://heartphp/admin/index の場合、正しいパスは tpl/admin/index/errorfile.html です
  60. * @return
  61. */
  62. public function display($filename = '', $view_path = '') {
  63. $ tpl_path_arr = $this->get_tpl($filename, $view_path );//TPL のフルパスを取得し、パスと名前をポインターに転送します
  64. if(!$tpl_path_arr) core::show_error($filename.$this- >_tpl_suffix.'テンプレートが存在しません');
  65. //コンパイルを開始します
  66. $this->gt;view_path_param = $view_path;//ユーザーによって渡されたテンプレートとディレクトリ
  67. $this->compile();
  68. }
  69. /**
  70. * コンパイルコントローラー
  71. * @param
  72. * @return
  73. */
  74. プライベート関数compile() {
  75. $filepath = $this->template_path.$this->template_name;
  76. $compile_dirpath = $this->check_temp_compile();
  77. $vars_template_c_name = str_replace($this->tpl_suffix, '', $this->template_name);
  78. $include_file = $this->template_replace($this->read_file($filepath), $compile_dirpath , $vars_template_c_name);//Parse
  79. if($include_file) {
  80. $this- >read_config() && $config = $this->read_config();
  81. extract($this->vars, EXTR_SKIP);
  82. [url=home.php?mod=space&uid=48608]@include[/url ] $include_file;
  83. }
  84. }
  85. /**
  86. * 現在のプロジェクト構成ファイルを読み取ります
  87. */
  88. 保護関数 read_config() {
  89. if(file_exists(SYSTEM_PATH) .'conf/config.php')) {
  90. @include SYSTEM_PATH.'conf/ config.php';
  91. return $config;
  92. }
  93. return false;
  94. }
  95. /**
  96. * テンプレート構文の解析
  97. * @param $str content
  98. * @param $compile_dirpath テンプレートのコンパイル ディレクトリ
  99. * @param $vars_template_c_name テンプレートのコンパイル ファイル名
  100. * @return コンパイル済みの PHP テンプレート ファイル名
  101. */
  102. プライベート関数 template_replace($str, $compile_dirpath, $vars_template_c_name) {
  103. if(empty($str)) core::show_error('テンプレートの内容が空です!');
  104. / /コンパイルヘッダーを処理します
  105. $compile_path = $compile_dirpath.$vars_template_c_name.$this->tpl_compile_suffix;//ファイルをコンパイルします
  106. if(is_file($compile_path)) {
  107. //$header_content = $this->gt;get_compile_header( $コンパイル_パス);
  108. //$compile_date = $this->get_compile_header_comment($header_content);
  109. $tpl_filemtime = filemtime($this->template_path.$this->template_name);
  110. $compile_filemtime = filemtime($compile_path );
  111. //echo $tpl_filemtime.'=='.date('Y-m-d H:i:s', $tpl_filemtime).'
    ';
  112. //echo $compile_filemtime.'== ' .date('Y-m-d H:i:s', $compile_filemtime);
  113. //ファイルの有効期限が切れている場合は、コンパイルし、テンプレート タグに include が含まれているため、再コンパイルも行われます
  114. //<{include file="public/ left.html"}> インクルード内のファイルを変更する場合、非DEBUGモードではメインファイルを変更しないと現状インクルード内のファイルは再コンパイルされません。これも変更するか検討中です。とりあえず考えてなかったので、開発段階では必ずDEBUG=1モードをONにしてください。そうしないとインクルードファイルの変更が無効になります。有点罗嗦,不知道表述明確没
  115. if($tpl_filemtime > $compile_filemtime || DEBUG) {
  116. $ret_file = $this->compile_file($vars_template_c_name, $str, $compile_dirpath);
  117. } else {
  118. $ ret_file = $compile_path;
  119. }
  120. } else {///编译文件不存在创建他
  121. $ret_file = $this->compile_file($vars_template_c_name, $str, $compile_dirpath);
  122. }
  123. return $ret_file;
  124. }
  125. /**
  126. * テンプレートファイル本体
  127. * @param string $str content
  128. * @return html
  129. */
  130. private function body_content($str) {
  131. //解析
  132. $str = $this->parse($str);
  133. $header_comment = "作成日##" .time()."|Compiled from##".$this->template_path.$this->template_name;
  134. $content = "rn$str";
  135. return $content;
  136. }
  137. /**
  138. * 関連するテンプレート タグの解析を開始します
  139. * @param $content テンプレート コンテンツ
  140. */
  141. プライベート関数 parse($content) {
  142. //foreach
  143. $content = $this->parse_foreach($content);
  144. //include
  145. $content = $this->parse_include($content);
  146. //if
  147. $content = $this->parse_if ($content);
  148. //elseif
  149. $content = $this->parse_elseif($content);
  150. //模板标签公用部分
  151. $content = $this->parse_comm($content);
  152. //转はphp代码
  153. $content = $this->parse_php($content);
  154. return $content;
  155. }
  156. /**
  157. * デフォルトで echo が直接 <{$config['domain']}> の場合、 に変換されます。*/
  158. private function parse_echo($content) {
  159. }
  160. /**
  161. * PHP に変換します
  162. * @param $content html テンプレートのコンテンツ
  163. * @return html HTML を置き換えます
  164. */
  165. プライベート関数 parse_php($content){
  166. if(empty($content)) return false;
  167. $content = preg_replace("/".$this->template_tag_left. "(.+?)".$this->template_tag_right."/is", "", $content);
  168. return $content;
  169. }
  170. /**
  171. * if判断语句
  172. * <{if empty($zhang)}>
  173. * zhang
  174. * <{elseif empty($liang)}>
  175. * liang
  176. * <{else}>
  177. *張良
  178. * <{/if}>
  179. */
  180. プライベート関数 parse_if($content) {
  181. if(empty($content)) return false;
  182. //preg_match_all("/".$this->template_tag_left."ifs+(.*?)".$this ->template_tag_right."/is", $content, $match);
  183. $match = $this->preg_match_all("ifs+(.*?)", $content);
  184. if(!isset($match) [1]) || !is_array($match[1])) return $content;
  185. foreach($match[1] as $k => $v) {
  186. //$s = preg_split("/s+ /is", $v);
  187. //$s = array_filter($s);
  188. $content = str_replace($match[0][$k], "", $content);
  189. }
  190. return $content;
  191. }
  192. private function parse_elseif($content) {
  193. if(empty($content)) return false;
  194. //preg_match_all("/".$ this->template_tag_left."elseifs+(.*?)".$this->template_tag_right."/is", $content, $match);
  195. $match = $this->preg_match_all("elseifs+(.* ?)", $content);
  196. if(!isset($match[1]) || !is_array($match[1])) return $content;
  197. foreach($match[1] as $k => $v) {
  198. //$s = preg_split("/s+/is", $v );
  199. //$s = array_filter($s);
  200. $content = str_replace($match[0][$k], "", $ content);
  201. }
  202. return $content;
  203. }
  204. /**
  205. * 解析 include include标签不是实時更新当本体文件更新的時才更新标签内容,想想include生效请修正一下本体文件
  206. * 记录一下有時间开出版一当DEBUGモード的時候每次执行删除モ版编译文件
  207. * 使用方法 <{include file="www.phpddt.com"}>
  208. * @param $content 模板内容
  209. * @return html
  210. */
  211. private function parse_include($content) {
  212. if(empty($content)) return false;
  213. //preg_match_all("/".$ this->template_tag_left."includes+(.*?)".$this->template_tag_right."/is", $content, $match);
  214. $match = $this->preg_match_all("includes+(.* ?)", $content);
  215. if(!isset($match[1]) || !is_array($match[1])) return $content;
  216. foreach($match[1] as $match_key => ; $match_value) {
  217. $a = preg_split("/s+/is", $match_value);
  218. $new_tag = array();
  219. // 分析元素
  220. foreach($a as $t) {
  221. $b = explode('=', $t);
  222. if(in_array($b[0], $this->tag_include)) {
  223. if(!empty($b[1])) {
  224. $new_tag[$b [0]] = str_replace(""", "", $b[1]);
  225. } else {
  226. core::show_error('模板路径不存在!');
  227. }
  228. }
  229. }
  230. extract( $new_tag);
  231. //模板文件
  232. foreach($this->conf['view_path'] as $v){
  233. $conf_view_tpl = $v.$file;//模板文件
  234. if(is_file($ conf_view_tpl)) {
  235. $c = $this->read_file($conf_view_tpl);
  236. $inc_file = str_replace($this->_tpl_suffix, '', Basename($file));
  237. $this-> ;view_path_param = dirname($file).'/';
  238. $compile_dirpath = $this->check_temp_compile();
  239. $include_file = $this->template_replace($c, $compile_dirpath, $inc_file);//解析
  240. Break;
  241. } else {
  242. core::show_error('模板文件不存在,请仔细检查文件:'. $conf_view_tpl);
  243. }
  244. }
  245. $content = str_replace($match[0][$match_key], '', $content);
  246. }
  247. return $content;
  248. }
  249. /**
  250. * foreach を解析します
  251. * 使用方法 <{foreach from=$lists item=value key=kk}>
  252. * @param $content template content
  253. * @return html 解析されたコンテンツ
  254. */
  255. private function parse_foreach($content) {
  256. if(empty($content)) return false;
  257. //preg_match_all("/" .$this->template_tag_left."foreachs+(.*?)".$this->template_tag_right."/is", $content, $match);
  258. $match = $this->preg_match_all("foreachs+( .*?)", $content);
  259. if(!isset($match[1]) || !is_array($match[1])) return $content;
  260. foreach($match[1] as $match_key => $value) {
  261. $split = preg_split("/s+/is", $value);
  262. $split = array_filter($split);
  263. $new_tag = array();
  264. foreach($split as $v) {
  265. $a =explode("=", $v);
  266. if(in_array($a[0], $this->tag_foreach)) {///此处过滤标签不存在过滤
  267. $new_tag [$a[0]] = $a[1];
  268. }
  269. }
  270. $key = '';
  271. extract($new_tag);
  272. $key = ($key) ? '$'.$key.' =>' : '' ;
  273. $s = '';
  274. $content = $this-> ;str_replace($match[0][$match_key], $s, $content);
  275. }
  276. return $content;
  277. }
  278. /**
  279. * 一致文字列の終わり
  280. */
  281. プライベート関数 parse_comm($content) {
  282. $search = array(
  283. "/".$this->template_tag_left."/foreach".$this->template_tag_right."/is",
  284. "/".$this->template_tag_left."/if ".$this->template_tag_right."/is",
  285. "/".$this->template_tag_left."else".$this->template_tag_right."/is",
  286. );
  287. $replace = array(
  288. "",
  289. "",
  290. ""
  291. );
  292. $content = preg_replace($ search、$replace、$content);
  293. return $content;
  294. }
  295. /**
  296. * コンパイルディレクトリを確認し、作成されていない場合は再帰的にディレクトリを作成します
  297. * @param string $path ファイルのフルパス
  298. * @return テンプレートの内容
  299. */
  300. プライベート関数 check_temp_compile() {
  301. //$paht = $this->template_c.
  302. $tpl_path = ($this->view_path_param) ? $this->view_path_param : $this->get_tpl_path() ;
  303. $all_tpl_apth = $this->template_c.$tpl_path;
  304. if(!is_dir($all_tpl_apth)) {
  305. $this->create_dir( $tpl_path);
  306. }
  307. return $all_tpl_apth;
  308. }
  309. /**
  310. * ファイルを読み取ります
  311. * @param string $path ファイルのフルパス
  312. * @return テンプレートの内容
  313. */
  314. プライベート関数 read_file($path) {
  315. //$this->check_file_limits($path, 'r');
  316. if(($r = @fopen($path, 'r')) === false) {
  317. core::show_error('模版文件没有读取または执行权限,请检查!');
  318. }
  319. $content = fread($r, filesize($path));
  320. fclose($r);
  321. return $content;
  322. }
  323. /**
  324. * ファイルの書き込み
  325. * @param string $filename ファイル名
  326. * @param string $content テンプレートのコンテンツ
  327. * @return ファイル名
  328. */
  329. プライベート関数compile_file($filename, $content, $dir) {
  330. if(empty($filename)) core::show_error("{$filename} 作成に失敗しました");
  331. $content = $this->body_content($content);//对文件内容操作
  332. //echo '开始编译了=====';
  333. $f = $dir.$filename.$this->tpl_compile_suffix;
  334. //$this->check_file_limits($f, 'w') ;
  335. if(($fp = @fopen($f, 'wb')) === false) {
  336. core::show_error($f.'
    编译文件失败,请检查文件权限。 ');
  337. }
  338. //开启flock
  339. flock($fp, LOCK_EX + LOCK_NB);
  340. fwrite($fp, $content, strlen($content));
  341. flock($fp, LOCK_UN + LOCK_NB);
  342. fclose ($fp);
  343. return $f;
  344. }
  345. /**
  346. * ファイルのパーミッションをチェックする機能は一時的に廃止されます
  347. * @param [$path] [path]
  348. * @param [status] [w=write, r=read]
  349. */
  350. public function check_file_limits($path , $status = 'rw') {
  351. clearstatcache();
  352. if(!is_writable( $path) && $status == 'w') {
  353. core::show_error("{$path}
    没有書入权限,请检查。");
  354. } elseif(!is_readable($path) ) && $status == 'r') {
  355. core::show_error("{$path}
    没有读取权限,请检查。");
  356. } elseif($status == 'rw' ) {//書き込みと読み取りをチェック
  357. if(!is_writable($path) || !is_readable($path)) {
  358. core::show_error("{$path}
    無し写入または读取权制限,请检查");
  359. }
  360. }
  361. }
  362. /* *
  363. * コンパイルされたテンプレートの最初の行を読み取り、配列に解析します
  364. * @param string $filepath ファイルパス
  365. * @param number $line 行数
  366. * @return は指定された行数の文字列を返します
  367. */
  368. /*
  369. プライベート関数 get_compile_header($filepath, $line = 0) {
  370. if(($file_arr = @file($filepath)) === false) {
  371. core::show_error( $filepath.'
    读取文件失败,请检查文件权限!');
  372. }
  373. return $file_arr[0];
  374. }
  375. */
  376. /**
  377. * ヘッダーコメントの分析日
  378. * @param string $cotnent コンパイルされたファイルのヘッダーの最初の行
  379. * @return 最後の日付を返します
  380. */
  381. /*
  382. プライベート関数 get_compile_header_comment($content) {
  383. preg_match("//*(.* ?)*//", $content, $match);
  384. if(!isset($match[1]) || empty($match[1])) core::show_error('コンパイル エラー!');
  385. $arr =explode('|', $match[1]);
  386. $arr_date =explode('##', $arr[0]);
  387. return $arr_date[1];
  388. }
  389. */
  390. / **
  391. * テンプレートのフルパスを取得し、既存のファイルを返します
  392. * @param string $filename ファイル名
  393. * @param string $view_path テンプレートのパス
  394. * @return
  395. */
  396. private function get_tpl($filename, $view_path) {
  397. empty($filename) && $filename = $this->tpl_name;
  398. //テンプレート パスをトラバースします
  399. foreach($this- > ;conf['view_path'] as $path) {
  400. if($view_path) {//tpl とディレクトリから直接ファイルを検索します
  401. $tpl_path = $path.$view_path;
  402. $view_file_path = $tpl_path.$filename.$ this ->tpl_suffix;
  403. } else {//ディレクトリ、コントローラー、メソッドに基づいてファイルの検索を開始します
  404. $view_file_path = ($tpl_path = $this->get_tpl_path($path)) $tpl_path.$filename.$ this- >_tpl_suffix : exit(0);
  405. }
  406. if(is_file($view_file_path)) {
  407. //テンプレートパスとテンプレート名をポインタに転送
  408. $this->template_path = $tpl_path;//
  409. $this- >template_name = $filename.$this->_tpl_suffix;
  410. return true;
  411. } else {
  412. core::show_error($filename.$this->_tpl_suffix.'テンプレートが存在しません');
  413. }
  414. }
  415. }
  416. /**
  417. * テンプレートのパスを取得します
  418. * @param string $path ホームディレクトリ
  419. * @return URL D と M の結合パス
  420. */
  421. プライベート関数 get_tpl_path($path = '') {
  422. core::get_directory_name() && $path_arr[0] = core::get_directory_name();
  423. core ::get_controller_name( ) && $path_arr[1] = core::get_controller_name();
  424. (is_array($path_arr)) $newpath = implode('/', $path_arr) : core::show_error('取得に失敗しましたテンプレート パス!') ;
  425. return $path.$newpath.'/';
  426. }
  427. /**
  428. * ディレクトリを作成します
  429. * @param string $path ディレクトリ
  430. * @return
  431. */
  432. プライベート関数 create_dir($path, $mode = 0777){
  433. if(is_dir( $path)) return false;
  434. $dir_arr =explode('/', $path);
  435. $dir_arr = array_filter($dir_arr);
  436. $allpath = '';
  437. $newdir = $this->template_c ;
  438. foreach( $dir_arr as $dir) {
  439. $allpath = $newdir.'/'.$dir;
  440. if(!is_dir($allpath)) {
  441. $newdir = $allpath;
  442. if(! @mkdir($allpath , $mode)) {
  443. core::show_error( $allpath.'
    ディレクトリの作成に失敗しました。書き込み権限があるかどうかを確認してください。 ');
  444. }
  445. chmod($allpath, $mode);
  446. } else {
  447. $newdir = $allpath;
  448. }
  449. }
  450. return true;
  451. }
  452. public function __destruct(){
  453. $this-> vars = null;
  454. $this->view_path_param = null;
  455. }
  456. };
コードをコピー


声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。