php MVC调度器和模板类功能实例

前端之家收集整理的这篇文章主要介绍了php MVC调度器和模板类功能实例前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
感兴趣的小伙伴,下面一起跟随编程之家 jb51.cc的小编来看看吧。
经测试代码如下:
  1. /**
  2. * MVC调度器和模板类
  3. *
  4. * @param
  5. * @author 编程之家 jb51.cc jb51.cc
  6. * {loop $array $key $value}..........{/loop} 循环
  7. * {loop $array $value}..........{/loop} 循环
  8. * {if condition}...{elseif condition}..{else}..{/if} if条件语句
  9. * {$val} 输出变量值
  10. * {eval echo"ok";} 运行PHP代码
  11. * {template file} 包含另外一个模版
  12. */
  13. class Template {
  14. private static $tDir; //模版文件目录
  15. private static $tTmpDir; //编译好后的文件目录
  16. private $tVal; //模版变量
  17. private $tFile; //模版文件
  18. private $tContent; //模版内容
  19. private static $uDispatcher; //URL调度器
  20. private static $real = false; //实时编译
  21. public function __construct() {
  22. $this->tVal = array();
  23. }
  24. /**
  25. * 设置模版文件目录
  26. * @param string $dir
  27. */
  28. public static function setTemplateDir($dir) {
  29. self::$tDir = $dir;
  30. }
  31. /**
  32. * 是否实时编译
  33. * @param bool $real
  34. */
  35. public static function setReal($real) {
  36. self::$real = (bool) $real;
  37. }
  38. /**
  39. * 临时文件目录
  40. * @param string $dir
  41. */
  42. public static function setTmpDir($dir) {
  43. if (!file_exists($dir)) {
  44. if (!mkdir($dir,true))
  45. die("tmp dir $dir can't to mkdir");
  46. }
  47. self::$tTmpDir = realpath($dir);
  48. }
  49. /**
  50. * URL调度器
  51. * @param Dispatcher $dispatcher
  52. */
  53. public static function setU(&$dispatcher) {
  54. if (is_object($dispatcher) && method_exists($dispatcher,'U')) {
  55. self::$uDispatcher = $dispatcher;
  56. }
  57. }
  58. /**
  59. * 变量赋值
  60. * @param mixed $name
  61. * @param mixed $value
  62. */
  63. public function assign($name,$value) {
  64. $this->tVal[$name] = $value;
  65. }
  66. /**
  67. * 取得模版的变量
  68. * @param string $name
  69. */
  70. public function getVal($name) {
  71. if (isset($this->tVal[$name])) {
  72. return $this->tVal[$name];
  73. }else
  74. return false;
  75. }
  76. /**
  77. * 将运行好后的内容,保存到一个html文件
  78. * @param string $tFile
  79. * @param string $html
  80. */
  81. public function saveHtml($tFile,$html) {
  82. ob_start();
  83. $this->display($tFile);
  84. $buffer = ob_get_contents();
  85. ob_end_clean();
  86. file_put_contents($html,$buffer);
  87. }
  88. /**
  89. * 运行并显示模版内容
  90. * @param string $tfile
  91. */
  92. public function display($tFile) {
  93. $this->tFile = $this->parseTemplatePath($tFile);
  94. if (!self::$real) {
  95. if (!file_exists($this->getTmpFile()))
  96. $this->parse();
  97. elseif ((filemtime($this->tFile) > filemtime($this->getTmpFile())))
  98. $this->parse();
  99. }else
  100. $this->parse();
  101. extract($this->tVal,EXTR_OVERWRITE);
  102. include $this->getTmpFile();
  103. }
  104. /**
  105. * 编译好后的文件
  106. * @return string $filepath
  107. */
  108. private function getTmpFile() {
  109. $basename = basename($this->tFile);
  110. $pos = strrpos($basename,'.');
  111. $tmp = 'tpl_' . substr($basename,$pos) . '.PHP';
  112. return self::$tTmpDir . '/' . $tmp;
  113. }
  114. private function parse() {
  115. $this->tContent = file_get_contents($this->tFile);
  116. $this->parseInclude();
  117. $this->parseSection();
  118. $this->parseVal();
  119. $this->parseEval();
  120. file_put_contents($this->getTmpFile(),$this->tContent);
  121. }
  122. private function parseInclude() {
  123. $this->tContent = preg_replace("/{templates+([a-zA-z0-9._]+)}/ies","$this->subtemplate('$1')",$this->tContent);
  124. }
  125. /**
  126. * 获取只模版
  127. * @param string $file
  128. */
  129. private function subtemplate($file) {
  130. return file_get_contents($this->parseTemplatePath($file));
  131. }
  132. /**
  133. * 解析模版路径
  134. * @param string $file
  135. * @return string $filepath
  136. */
  137. private function parseTemplatePath($tFile) {
  138. $tFile.='.html';
  139. $tFile = self::$tDir ? self::$tDir . '/' . $tFile : $tFile;
  140. if (!file_exists($tFile)) {
  141. die("No template file $tFile");
  142. } else {
  143. $tFile = realpath($tFile);
  144. }
  145. return $tFile;
  146. }
  147. /**
  148. * 解析变量
  149. */
  150. private function parseVal() {
  151. $this->tContent = preg_replace("/{(\$S+?)}/is","<?PHP echo \1 ;?>",$this->tContent);
  152. }
  153. /**
  154. * 解析段落
  155. */
  156. private function parseSection() {
  157. //逻辑
  158. $this->tContent = preg_replace("/{elseifs+(.+?)}/ies","$this->stripvtags('<?PHP } elseif(\1) { ?>','')",$this->tContent);
  159. $this->tContent = preg_replace("/{else}/is","<?PHP } else { ?>",$this->tContent);
  160. $this->tContent = preg_replace("/{U((.+?))}/ies","$this->parseUrl('$1')",$this->tContent);
  161. //循环
  162. for ($i = 0; $i < 6; $i++) {
  163. $this->tContent = preg_replace("/{loops+(S+)s+(S+)}(.+?){/loop}/ies","$this->stripvtags('<?PHP if(is_array(\1)) { foreach(\1 as \2) { ?>','\3<?PHP } } ?>')",$this->tContent);
  164. $this->tContent = preg_replace("/{loops+(S+)s+(S+)s+(S+)}(.+?){/loop}/ies","$this->stripvtags('<?PHP if(is_array(\1)) { foreach(\1 as \2 => \3) { ?>','\4<?PHP } } ?>')",$this->tContent);
  165. $this->tContent = preg_replace("/{ifs+(.+?)}(.+?){/if}/ies","$this->stripvtags('<?PHP if(\1) { ?>','\2<?PHP } ?>')",$this->tContent);
  166. }
  167. }
  168. private function stripvtags($expr,$statement='') {
  169. $expr = str_replace("\"",""",preg_replace("/<?=(\$.+?)?>/s","\1",$expr));
  170. $statement = str_replace("\"",$statement);
  171. return $expr . $statement;
  172. }
  173. /**
  174. * 解析PHP语句
  175. */
  176. private function parseEval() {
  177. $this->tContent = preg_replace("/{evals+(.+?)}/is","<?PHP $1 ?>",$this->tContent);
  178. }
  179. /**
  180. * 解析URL
  181. */
  182. private function parseUrl($url) {
  183. if (is_object(self::$uDispatcher)) {
  184. return self::$uDispatcher->U($url);
  185. } else {
  186. return $url;
  187. }
  188. }
  189. }
  190. ?>
  191. <?PHP
  192. /**
  193. * 控制调度器
  194. * 先定义APP_PATH常量 制定应用程序目录
  195. * 默认模块目录 APP_PATH 目录下面的 Action目录
  196. * 默认控制器为IndexAction
  197. * 默认模块名为index
  198. * 默认参数分隔符为"/",可选"-"
  199. * 默认入口文件为index.PHP
  200. * 模块的类名必须和文件同名,比如:IndexModule则它的文件名为IndexModule.class.PHP
  201. * 可通过setOption方法设置一些参数
  202. * pathinfo模式支持伪静态
  203. * 新增普通url模式
  204. * setOption参数说明
  205. * 传进去的是数组键值对形式的参数
  206. * 设置选项条件,可设置的有
  207. * MODULE_PATH=>查找模块目录的位置
  208. * DEFAULT_MODULE=>默认Module
  209. * DEFAULT_ACTION=>默认Action
  210. * DEBUG=>开启调试(true|false)
  211. * URL_MODEL=>路由模式(0:普通模式,1:pathinfo模式)
  212. * URL_DELIMITER=>参数分隔符 pathinfo模式使用
  213. * URL_HTML_SUFFIX=>'文件后缀' pathinfo模式伪静态使用
  214. * ENTRY_INDEX=>入口文件
  215. * URL_ROUTER_ON=>开启自定义路由
  216. * 普通URL模式U(模块名/操作名?参1=值1&参2=值2)
  217. * 路由模式U(路由名@?参1=值1&参2=值2)
  218. */
  219. class Dispatcher {
  220. private static $instance;
  221. private static $_SGLOBAL; //调度配置
  222. private static $route = array(); //泛路由
  223. private function __construct() {
  224. self::initConfig();
  225. }
  226. public static function getInstance() {
  227. if (!self::$instance instanceof self) {
  228. self::$instance = new self();
  229. }
  230. return self::$instance;
  231. }
  232. private function __clone() {
  233. }
  234. /**
  235. * 运行控制器
  236. */
  237. public function run() {
  238. $route = array();
  239. if (self::$_SGLOBAL['URL_MODEL'] == 1) {
  240. $route = $this->pathInfoRoute();
  241. } else {
  242. $route = $this->generalRoute();
  243. }
  244. $modulefile = self::$_SGLOBAL['MODULE_PATH'] ."/{$route['module']}.class.PHP";
  245. if (file_exists($modulefile)) {
  246. include $modulefile;
  247. if (class_exists($route['module'])) {
  248. $class = new $route['module'];
  249. if (method_exists($class,$route['action'])) {
  250. call_user_func(array(&$class,$route['action']));
  251. }else
  252. die("in <b>{$route['module']}</b> module no this <b>{$route['action']}</b> action");
  253. }else
  254. die("no this <b>{$route['module']}</b> module");
  255. }else {
  256. die("no this <b>{$route['module']}</b> module");
  257. }
  258. self::$_SGLOBAL['endtime'] = microtime(true);
  259. $this->debugInfo();
  260. }
  261. /**
  262. * 输出调试信息
  263. */
  264. private function debugInfo() {
  265. if (self::$_SGLOBAL['DEBUG']) {
  266. $exectime = self::$_SGLOBAL['endtime'] - self::$_SGLOBAL['starttime'];
  267. $debuginfo = <<<HTML
  268. <style type="text/css">
  269. .dispatcher_debug_table th,.dispatcher_debug_table td{padding:5px;}
  270. .dispatcher_debug_table th{
  271. border-top:1px solid red;
  272. border-left:1px solid red;
  273. background-color:#ccc;
  274. }
  275. .dispatcher_debug_table td{
  276. border-top:1px solid red;
  277. border-left:1px solid red;
  278. border-right:1px solid red;
  279. }
  280. .dispatcher_debug_table_last td,.dispatcher_debug_table_last th{
  281. border-bottom:1px solid red;
  282. }
  283. .dispatcher_debug_table_title{border-right:1px solid red;}
  284. </style>
  285. <table class="dispatcher_debug_table"cellpadding="0"cellspacing="0">
  286. <tr><th class="dispatcher_debug_table_title">Debug Info</th></tr>
  287. <tr>
  288. <th>Execute Time</th><td>$exectime s</td>
  289. </tr>
  290. <tr><th>Include File</th><td>
  291. HTML;
  292. foreach (get_included_files () as $file) {
  293. $debuginfo.=$file ."<br/>";
  294. }
  295. $debuginfo.="<tr><th>Server Info</th><td>";
  296. $debuginfo.="Host:". $_SERVER['HTTP_HOST'] ."<br/>";
  297. $debuginfo.="PHP_Version:". PHP_VERSION ."<br/>";
  298. $debuginfo.="Server_Version:". $_SERVER['SERVER_SOFTWARE'] ."<br/>";
  299. $debuginfo.="</td></tr>";
  300. $debuginfo.="<tr class='dispatcher_debug_table_last'><th>Client Info</th><td>";
  301. $debuginfo.="Remote_Addr:". $_SERVER['REMOTE_ADDR'] ."<br/>";
  302. $debuginfo.="User_Agent:". $_SERVER['HTTP_USER_AGENT'] ."<br/>";
  303. $debuginfo.="</td></tr>";
  304. $debuginfo.="</table>";
  305. echo $debuginfo;
  306. }
  307. }
  308. private function generalRoute() {
  309. $route = array();
  310. $route['module'] = !empty($_GET['m']) ? $_GET['m'] : self::$_SGLOBAL['DEFAULT_MODULE'];
  311. $route['action'] = !empty($_GET['a']) ? $_GET['a'] : self::$_SGLOBAL['DEFAULT_ACTION'];
  312. $route['module'].='Action';
  313. unset($_GET['m']);
  314. unset($_GET['a']);
  315. return $route;
  316. }
  317. /**
  318. * PATHINFO形式的路由调度
  319. * 支持伪静态
  320. */
  321. private function pathInfoRoute() {
  322. $route = array();
  323. //伪静态
  324. if (self::$_SGLOBAL['URL_HTML_SUFFIX']) {
  325. $pos = strlen($_SERVER['PATH_INFO']) - strlen(self::$_SGLOBAL['URL_HTML_SUFFIX']);
  326. $_SERVER['PATH_INFO'] = substr($_SERVER['PATH_INFO'],$pos);
  327. }
  328. if (!$_SERVER['PATH_INFO'] || $_SERVER['PATH_INFO'] == '/') {
  329. $route = array('module' => self::$_SGLOBAL['DEFAULT_MODULE'],'action' => self::$_SGLOBAL['DEFAULT_ACTION']);
  330. } else {
  331. $_SERVER['PATH_INFO'] = substr($_SERVER['PATH_INFO'],1);
  332. $pathinfo = explode(self::$_SGLOBAL['URL_DELIMITER'],$_SERVER['PATH_INFO']);
  333. //用户自定义路由
  334. if (self::$_SGLOBAL['URL_ROUTER_ON'] && in_array($pathinfo[0],array_keys(self::$route))) {
  335. $route['module'] = self::$route[$pathinfo[0]][0];
  336. $route['action'] = self::$route[$pathinfo[0]][1];
  337. $c = explode(',',self::$route[$pathinfo[0]][2]);
  338. array_shift($pathinfo);
  339. foreach ($c as $r) {
  340. $_GET[$r] = array_shift($pathinfo);
  341. }
  342. } else {
  343. if (count($pathinfo) < 2) {
  344. $route['module'] = $pathinfo[0] . self::$_SGLOBAL['MODULE_SUFFIX'];
  345. $route['action'] = self::$_SGLOBAL['DEFAULT_ACTION'] . self::$_SGLOBAL['ACTION_SUFFIX'];
  346. } else {
  347. $route['module'] = array_shift($pathinfo) . self::$_SGLOBAL['MODULE_SUFFIX'];
  348. $route['action'] = array_shift($pathinfo) . self::$_SGLOBAL['ACTION_SUFFIX'];
  349. }
  350. }
  351. if (count($pathinfo) >= 2) {
  352. for ($i = 0,$cnt = count($pathinfo); $i < $cnt; $i++) {
  353. if (isset($pathinfo[$i + 1])) {
  354. $_GET[$pathinfo[$i]] = $pathinfo[++$i];
  355. }
  356. }
  357. }
  358. }
  359. $route['module'].='Action';
  360. $_REQUEST = array_merge($_GET,$_POST);
  361. return $route;
  362. }
  363. /**
  364. * URL地址组合
  365. * 格式为:Module/Action?get=par(模块名/动作名?get参数)
  366. * @param string $url
  367. * @return string $url
  368. */
  369. public static function U($url) {
  370. $pathinfo = parse_url($url);
  371. $path = '';
  372. $get = array();
  373. $inroute = false; //用户定义的路由
  374. if (isset($pathinfo['query'])) {
  375. $query = explode('&',$pathinfo['query']);
  376. foreach ($query as $q) {
  377. list($k,$v) = explode('=',$q);
  378. $get[$k] = $v;
  379. }
  380. }
  381. if (!self::$_SGLOBAL) {
  382. self::initConfig();
  383. }
  384. //pathinfo方式的url
  385. if (self::$_SGLOBAL['URL_MODEL'] == 1) {
  386. if (self::$_SGLOBAL['URL_ROUTER_ON'] && strpos($pathinfo['path'],'@') !== false) {
  387. //取出所有用户定义的路由
  388. $routeNames = array_keys(self::$route);
  389. $p = substr($pathinfo['path'],-1);
  390. if (in_array($p,$routeNames)) {
  391. $inroute = true;
  392. $path.='/' . $p;
  393. $c = explode(',self::$route[$p][2]);
  394. foreach ($c as $v) {
  395. if (isset($get[$v])) {
  396. $path.=self::$_SGLOBAL['URL_DELIMITER'] . $get[$v];
  397. unset($get[$v]);
  398. }
  399. }
  400. }
  401. }
  402. if (!$inroute) {
  403. if (isset($pathinfo['path'])) {
  404. list($module,$action) = explode('/',$pathinfo['path']);
  405. $module = $module ? $module : self::$_SGLOBAL['DEFAULT_MODULE'];
  406. $action = $action ? $action : self::$_SGLOBAL['DEFAULT_ACTION'];
  407. } else {
  408. $module = self::$_SGLOBAL['DEFAULT_MODULE'];
  409. $action = self::$_SGLOBAL['DEFAULT_ACTION'];
  410. }
  411. $path ="/$module". self::$_SGLOBAL['URL_DELIMITER'] . $action;
  412. }
  413. if (!empty($get)) {
  414. foreach ($get as $k => $v) {
  415. $path.=self::$_SGLOBAL['URL_DELIMITER'] . $k . self::$_SGLOBAL['URL_DELIMITER'] . $v;
  416. }
  417. }
  418. //url伪静态
  419. if (self::$_SGLOBAL['URL_HTML_SUFFIX']) {
  420. $path.=self::$_SGLOBAL['URL_HTML_SUFFIX'];
  421. }
  422. } elseif (self::$_SGLOBAL['URL_MODEL'] == 0) {
  423. $url = parse_url($url);
  424. if (isset($url['path'])) {
  425. list($module,$url['path']);
  426. $module = $module ? $module : self::$_SGLOBAL['DEFAULT_MODULE'];
  427. $action = $action ? $action : self::$_SGLOBAL['DEFAULT_ACTION'];
  428. } else {
  429. $module = self::$_SGLOBAL['DEFAULT_MODULE'];
  430. $action = self::$_SGLOBAL['DEFAULT_ACTION'];
  431. }
  432. $path.="?m=$module&a=$action";
  433. if ($url['query']) {
  434. $path.='&' . $url['query'];
  435. }
  436. }
  437. if (!self::$_SGLOBAL['URL_REWRITE'])
  438. $path = '/' . self::$_SGLOBAL['ENTRY_INDEX'] . $path;
  439. return $path;
  440. }
  441. /**
  442. * 初始化配置信息
  443. */
  444. private static function initConfig() {
  445. if (defined('APP_PATH')) {
  446. //默认模块目录
  447. self::$_SGLOBAL['MODULE_PATH'] = APP_PATH . '/action';
  448. }
  449. self::$_SGLOBAL['DEFAULT_ACTION'] = 'index'; //默认action
  450. self::$_SGLOBAL['DEFAULT_MODULE'] = 'Index'; //默认module
  451. //默认url路由模式,1:pathinfo模式,0为普通模式
  452. self::$_SGLOBAL['URL_MODEL'] = 1;
  453. self::$_SGLOBAL['URL_DELIMITER'] = '/'; //参数分隔符
  454. self::$_SGLOBAL['ENTRY_INDEX'] = 'index.PHP';
  455. self::$_SGLOBAL['URL_HTML_SUFFIX'] = null; //url伪静态
  456. self::$_SGLOBAL['URL_REWRITE'] = false; //URL重写
  457. self::$_SGLOBAL['starttime'] = microtime(true);
  458. self::$_SGLOBAL['URL_ROUTER_ON'] = false; //是否启用路由功能
  459. self::$_SGLOBAL['DEBUG'] = false;
  460. }
  461. /**
  462. * 设置选项条件,可设置的有
  463. * MODULE_PATH=>查找模块目录的位置
  464. * DEFAULT_MODULE=>默认Module
  465. * DEFAULT_ACTION=>默认Action
  466. * DEBUG=>开启调试(true|false)
  467. * URL_DELIMITER=>参数分隔符
  468. * URL_MODEL=>路由模式(0:普通模式,1:pathinfo模式)
  469. * URL_HTML_SUFFIX=>'文件后缀' pathinfo模式伪静态使用
  470. * ENTRY_INDEX=>入口文件
  471. * URL_ROUTER_ON=>开启自定义路由
  472. * @param array $option 选项
  473. */
  474. public function setOption($option) {
  475. $o = array('MODULE_PATH','DEFAULT_MODULE','DEFAULT_ACTION','DEBUG','URL_DELIMITER','URL_MODEL','URL_HTML_SUFFIX','ENTRY_INDEX','URL_REWRITE','URL_ROUTER_ON');
  476. foreach ($option as $k => $v) {
  477. if (in_array($k,$o)) {
  478. self::$_SGLOBAL[$k] = $v;
  479. }
  480. }
  481. }
  482. /**
  483. * 设置路由
  484. * array('route'=>array('模块名称','操作名称','参数1,参数2,参数3'))
  485. * @param array $route 路由
  486. */
  487. public function setRoute($route) {
  488. self::$route = $route;
  489. }
  490. }
  491. ?>
  492. <?PHP
  493. include 'action/CommonAction.class.PHP';
  494. require 'mvc/Dispatcher.class.PHP';
  495. require 'mvc/Template.class.PHP';
  496. $dispatcher = Dispatcher::getInstance();
  497. //控制器选项
  498. $option = array('DEBUG' => 1,'URL_MODEL' => 1,'URL_DELIMITER' => '/','DEFAULT_ACTION' => 'home','URL_REWRITE' => 1,'URL_ROUTER_ON' => true,'URL_HTML_SUFFIX'=>'.html');
  499. //自定义泛路由
  500. $router = array('space'=>array('Space','index','uid'));
  501. $dispatcher->setOption($option);
  502. $dispatcher->setRoute($router);
  503. Template::setU($dispatcher);
  504. Template::setReal(true);
  505. Template::setTemplateDir('template/default');
  506. Template::setTmpDir('runtime/tpl');
  507. $dispatcher->run();

猜你在找的PHP相关文章