Maison  >  Article  >  php教程  >  MVC的调度器和模板类

MVC的调度器和模板类

PHP中文网
PHP中文网original
2016-05-25 17:15:091324parcourir

调整了设置参数的的方法

新增了普通路由模式

pathinfo模式支持伪静态了

pathinfo现在支持用户自定义路由了  

<?php

/**
 * {loop $array $key $value}..........{/loop} 循环
 * {loop $array $value}..........{/loop} 循环
 * {if condition}...{elseif condition}..{else}..{/if} if条件语句
 * {$val} 输出变量值
 * {eval echo"ok";} 运行PHP代码
 * {template file} 包含另外一个模版
*/
class Template {

 private static $tDir; //模版文件目录
 private static $tTmpDir; //编译好后的文件目录
 private $tVal; //模版变量
 private $tFile; //模版文件
 private $tContent; //模版内容
 private static $uDispatcher; //URL调度器
 private static $real = false; //实时编译

 public function __construct() {
 $this->tVal = array();
}

/**
 * 设置模版文件目录
 * @param string $dir
*/
 public static function setTemplateDir($dir) {
 self::$tDir = $dir;
}

/**
 * 是否实时编译
 * @param bool $real
*/
 public static function setReal($real) {
 self::$real = (bool) $real;
}

/**
 * 临时文件目录
 * @param string $dir
*/
 public static function setTmpDir($dir) {
 if (!file_exists($dir)) {
 if (!mkdir($dir, 0, true))
 die("tmp dir $dir can&#39;t to mkdir");
}
 self::$tTmpDir = realpath($dir);
}

/**
 * URL调度器
 * @param Dispatcher $dispatcher
*/
 public static function setU(&$dispatcher) {
 if (is_object($dispatcher) && method_exists($dispatcher, &#39;U&#39;)) {
 self::$uDispatcher = $dispatcher;
}
}

/**
 * 变量赋值
 * @param mixed $name
 * @param mixed $value
*/
 public function assign($name, $value) {
 $this->tVal[$name] = $value;
}

/**
 * 取得模版的变量
 * @param string $name
*/
 public function getVal($name) {
 if (isset($this->tVal[$name])) {
 return $this->tVal[$name];
}else
 return false;
}

/**
 * 将运行好后的内容,保存到一个html文件中
 * @param string $tFile
 * @param string $html
*/
 public function saveHtml($tFile, $html) {
ob_start();
$this->display($tFile);
 $buffer = ob_get_contents();
ob_end_clean();
 file_put_contents($html, $buffer);
}

/**
 * 运行并显示模版内容
 * @param string $tfile
*/
 public function display($tFile) {
 $this->tFile = $this->parseTemplatePath($tFile);
 if (!self::$real) {
 if (!file_exists($this->getTmpFile()))
$this->parse();
 elseif ((filemtime($this->tFile) > filemtime($this->getTmpFile())))
$this->parse();
}else
$this->parse();
 extract($this->tVal, EXTR_OVERWRITE);
 include $this->getTmpFile();
}

/**
 * 编译好后的文件
 * @return string $filepath
*/
 private function getTmpFile() {
 $basename = basename($this->tFile);
 $pos = strrpos($basename, &#39;.&#39;);
 $tmp = &#39;tpl_&#39; . substr($basename, 0, $pos) . &#39;.php&#39;;
 return self::$tTmpDir . &#39;/&#39; . $tmp;
}

 private function parse() {
 $this->tContent = file_get_contents($this->tFile);
$this->parseInclude();
$this->parseSection();
$this->parseVal();
$this->parseEval();
 file_put_contents($this->getTmpFile(), $this->tContent);
}

 private function parseInclude() {
 $this->tContent = preg_replace("/{templates+([a-zA-z0-9._]+)}/ies","$this->subtemplate(&#39;$1&#39;)", $this->tContent);
}

/**
 * 获取只模版
 * @param string $file
*/
 private function subtemplate($file) {
 return file_get_contents($this->parseTemplatePath($file));
}

/**
 * 解析模版路径
 * @param string $file
 * @return string $filepath
*/
 private function parseTemplatePath($tFile) {
$tFile.=&#39;.html&#39;;
 $tFile = self::$tDir ? self::$tDir . &#39;/&#39; . $tFile : $tFile;
 if (!file_exists($tFile)) {
 die("No template file $tFile");
 } else {
 $tFile = realpath($tFile);
}
 return $tFile;
}

/**
 * 解析变量
*/
 private function parseVal() {
 $this->tContent = preg_replace("/{(\$S+?)}/is","<?php echo \1 ;?>", $this->tContent);
}

/**
 * 解析段落
*/
 private function parseSection() {
//逻辑
 $this->tContent = preg_replace("/{elseifs+(.+?)}/ies","$this->stripvtags(&#39;<?php } elseif(\1) { ?>&#39;,&#39;&#39;)", $this->tContent);
 $this->tContent = preg_replace("/{else}/is","<?php } else { ?>", $this->tContent);
 $this->tContent = preg_replace("/{U((.+?))}/ies","$this->parseUrl(&#39;$1&#39;)", $this->tContent);
//循环
 for ($i = 0; $i < 6; $i++) {
 $this->tContent = preg_replace("/{loops+(S+)s+(S+)}(.+?){/loop}/ies","$this->stripvtags(&#39;<?php if(is_array(\1)) { foreach(\1 as \2) { ?>&#39;,&#39;\3<?php } } ?>&#39;)", $this->tContent);
 $this->tContent = preg_replace("/{loops+(S+)s+(S+)s+(S+)}(.+?){/loop}/ies","$this->stripvtags(&#39;<?php if(is_array(\1)) { foreach(\1 as \2 => \3) { ?>&#39;,&#39;\4<?php } } ?>&#39;)", $this->tContent);
 $this->tContent = preg_replace("/{ifs+(.+?)}(.+?){/if}/ies","$this->stripvtags(&#39;<?php if(\1) { ?>&#39;,&#39;\2<?php } ?>&#39;)", $this->tContent);
}
}

 private function stripvtags($expr, $statement=&#39;&#39;) {
 $expr = str_replace("\"",""", preg_replace("/<?=(\$.+?)?>/s","\1", $expr));
 $statement = str_replace("\"",""", $statement);
 return $expr . $statement;
}

/**
 * 解析PHP语句
*/
 private function parseEval() {
 $this->tContent = preg_replace("/{evals+(.+?)}/is","<?php $1 ?>", $this->tContent);
}

/**
 * 解析URL
*/
 private function parseUrl($url) {
 if (is_object(self::$uDispatcher)) {
 return self::$uDispatcher->U($url);
 } else {
 return $url;
}
}
}
?>


<?php

/**
 * 控制调度器
 * 先定义APP_PATH常量 制定应用程序目录
 * 默认模块目录 APP_PATH 目录下面的 Action目录
 * 默认控制器为IndexAction
 * 默认模块名为index
 * 默认参数分隔符为"/",可选"-"
 * 默认入口文件为index.php
 * 模块的类名必须和文件同名,比如:IndexModule则它的文件名为IndexModule.class.php
 * 可通过setOption方法设置一些参数
 * pathinfo模式支持伪静态
 * 新增普通url模式
 * setOption参数说明
 * 传进去的是数组键值对形式的参数
 * 设置选项条件,可设置的有
 * MODULE_PATH=>查找模块目录的位置
 * DEFAULT_MODULE=>默认Module
 * DEFAULT_ACTION=>默认Action
 * DEBUG=>开启调试(true|false)
 * URL_MODEL=>路由模式(0:普通模式,1:pathinfo模式)
 * URL_DELIMITER=>参数分隔符 pathinfo模式使用
 * URL_HTML_SUFFIX=>&#39;文件后缀&#39; pathinfo模式伪静态使用
 * ENTRY_INDEX=>入口文件
 * URL_ROUTER_ON=>开启自定义路由
 * 普通URL模式U(模块名/操作名?参1=值1&参2=值2)
 * 路由模式U(路由名@?参1=值1&参2=值2)
*/
class Dispatcher {

 private static $instance;
 private static $_SGLOBAL; //调度配置
 private static $route = array(); //泛路由

 private function __construct() {
self::initConfig();
}

 public static function getInstance() {
 if (!self::$instance instanceof self) {
 self::$instance = new self();
}
 return self::$instance;
}

 private function __clone() {

}

/**
 * 运行控制器
*/
 public function run() {
 $route = array();
 if (self::$_SGLOBAL[&#39;URL_MODEL&#39;] == 1) {
 $route = $this->pathInfoRoute();
 } else {
 $route = $this->generalRoute();
}
 $modulefile = self::$_SGLOBAL[&#39;MODULE_PATH&#39;] ."/{$route[&#39;module&#39;]}.class.php";
 if (file_exists($modulefile)) {
 include $modulefile;
 if (class_exists($route[&#39;module&#39;])) {
 $class = new $route[&#39;module&#39;];
 if (method_exists($class, $route[&#39;action&#39;])) {
 call_user_func(array(&$class, $route[&#39;action&#39;]));
}else
 die("in <b>{$route[&#39;module&#39;]}</b> module no this <b>{$route[&#39;action&#39;]}</b> action");
}else
 die("no this <b>{$route[&#39;module&#39;]}</b> module");
 }else {
 die("no this <b>{$route[&#39;module&#39;]}</b> module");
}
 self::$_SGLOBAL[&#39;endtime&#39;] = microtime(true);
$this->debugInfo();
}

/**
 * 输出调试信息
*/
 private function debugInfo() {
 if (self::$_SGLOBAL[&#39;DEBUG&#39;]) {
 $exectime = self::$_SGLOBAL[&#39;endtime&#39;] - self::$_SGLOBAL[&#39;starttime&#39;];
 $debuginfo = <<<HTML
 <style type="text/css">
 .dispatcher_debug_table th,.dispatcher_debug_table td{padding:5px;}
 .dispatcher_debug_table th{
 border-top:1px solid red;
 border-left:1px solid red;
background-color:#ccc;
}
 .dispatcher_debug_table td{
 border-top:1px solid red;
 border-left:1px solid red;
 border-right:1px solid red;
}
.dispatcher_debug_table_last td,.dispatcher_debug_table_last th{
 border-bottom:1px solid red;
}
 .dispatcher_debug_table_title{border-right:1px solid red;}

</style>
 <table class="dispatcher_debug_table"cellpadding="0"cellspacing="0">
 <tr><th class="dispatcher_debug_table_title">Debug Info</th></tr>
<tr>
 <th>Execute Time</th><td>$exectime s</td>
</tr>
 <tr><th>Include File</th><td>
HTML;
 foreach (get_included_files () as $file) {
 $debuginfo.=$file ."<br/>";
}
 $debuginfo.="<tr><th>Server Info</th><td>";
 $debuginfo.="Host:". $_SERVER[&#39;HTTP_HOST&#39;] ."<br/>";
 $debuginfo.="PHP_Version:". PHP_VERSION ."<br/>";
 $debuginfo.="Server_Version:". $_SERVER[&#39;SERVER_SOFTWARE&#39;] ."<br/>";
$debuginfo.="</td></tr>";
 $debuginfo.="<tr class=&#39;dispatcher_debug_table_last&#39;><th>Client Info</th><td>";
 $debuginfo.="Remote_Addr:". $_SERVER[&#39;REMOTE_ADDR&#39;] ."<br/>";
 $debuginfo.="User_Agent:". $_SERVER[&#39;HTTP_USER_AGENT&#39;] ."<br/>";
$debuginfo.="</td></tr>";
$debuginfo.="</table>";
 echo $debuginfo;
}
}

 private function generalRoute() {
 $route = array();
 $route[&#39;module&#39;] = !empty($_GET[&#39;m&#39;]) ? $_GET[&#39;m&#39;] : self::$_SGLOBAL[&#39;DEFAULT_MODULE&#39;];
 $route[&#39;action&#39;] = !empty($_GET[&#39;a&#39;]) ? $_GET[&#39;a&#39;] : self::$_SGLOBAL[&#39;DEFAULT_ACTION&#39;];
$route[&#39;module&#39;].=&#39;Action&#39;;
unset($_GET[&#39;m&#39;]);
unset($_GET[&#39;a&#39;]);
 return $route;
}

/**
 * PATHINFO形式的路由调度
 * 支持伪静态
*/
 private function pathInfoRoute() {
 $route = array();
//伪静态
 if (self::$_SGLOBAL[&#39;URL_HTML_SUFFIX&#39;]) {
 $pos = strlen($_SERVER[&#39;PATH_INFO&#39;]) - strlen(self::$_SGLOBAL[&#39;URL_HTML_SUFFIX&#39;]);
 $_SERVER[&#39;PATH_INFO&#39;] = substr($_SERVER[&#39;PATH_INFO&#39;], 0, $pos);
}
 if (!$_SERVER[&#39;PATH_INFO&#39;] || $_SERVER[&#39;PATH_INFO&#39;] == &#39;/&#39;) {
 $route = array(&#39;module&#39; => self::$_SGLOBAL[&#39;DEFAULT_MODULE&#39;],
 &#39;action&#39; => self::$_SGLOBAL[&#39;DEFAULT_ACTION&#39;]);
 } else {
 $_SERVER[&#39;PATH_INFO&#39;] = substr($_SERVER[&#39;PATH_INFO&#39;], 1);
 $pathinfo = explode(self::$_SGLOBAL[&#39;URL_DELIMITER&#39;], $_SERVER[&#39;PATH_INFO&#39;]);
//用户自定义路由
 if (self::$_SGLOBAL[&#39;URL_ROUTER_ON&#39;] && in_array($pathinfo[0], array_keys(self::$route))) {
 $route[&#39;module&#39;] = self::$route[$pathinfo[0]][0];
 $route[&#39;action&#39;] = self::$route[$pathinfo[0]][1];
 $c = explode(&#39;,&#39;, self::$route[$pathinfo[0]][2]);
array_shift($pathinfo);
 foreach ($c as $r) {
 $_GET[$r] = array_shift($pathinfo);
}
 } else {
 if (count($pathinfo) < 2) {
 $route[&#39;module&#39;] = $pathinfo[0] . self::$_SGLOBAL[&#39;MODULE_SUFFIX&#39;];
 $route[&#39;action&#39;] = self::$_SGLOBAL[&#39;DEFAULT_ACTION&#39;] . self::$_SGLOBAL[&#39;ACTION_SUFFIX&#39;];
 } else {
 $route[&#39;module&#39;] = array_shift($pathinfo) . self::$_SGLOBAL[&#39;MODULE_SUFFIX&#39;];
 $route[&#39;action&#39;] = array_shift($pathinfo) . self::$_SGLOBAL[&#39;ACTION_SUFFIX&#39;];
}
}
 if (count($pathinfo) >= 2) {
 for ($i = 0, $cnt = count($pathinfo); $i < $cnt; $i++) {
 if (isset($pathinfo[$i + 1])) {
 $_GET[$pathinfo[$i]] = $pathinfo[++$i];
}
}
}
}
$route[&#39;module&#39;].=&#39;Action&#39;;
 $_REQUEST = array_merge($_GET, $_POST);
 return $route;
}

/**
 * url地址组合
 * 格式为:Module/Action?get=par(模块名/动作名?get参数)
 * @param string $url
 * @return string $url
*/
 public static function U($url) {
 $pathinfo = parse_url($url);
 $path = &#39;&#39;;
 $get = array();
 $inroute = false; //用户定义的路由
 if (isset($pathinfo[&#39;query&#39;])) {
 $query = explode(&#39;&&#39;, $pathinfo[&#39;query&#39;]);
 foreach ($query as $q) {
 list($k, $v) = explode(&#39;=&#39;, $q);
 $get[$k] = $v;
}
}

 if (!self::$_SGLOBAL) {
self::initConfig();
}
//pathinfo方式的url
 if (self::$_SGLOBAL[&#39;URL_MODEL&#39;] == 1) {

 if (self::$_SGLOBAL[&#39;URL_ROUTER_ON&#39;] && strpos($pathinfo[&#39;path&#39;], &#39;@&#39;) !== false) {
//取出所有用户定义的路由
 $routeNames = array_keys(self::$route);
 $p = substr($pathinfo[&#39;path&#39;], 0, -1);
 if (in_array($p, $routeNames)) {
 $inroute = true;
 $path.=&#39;/&#39; . $p;
 $c = explode(&#39;,&#39;, self::$route[$p][2]);
 foreach ($c as $v) {
 if (isset($get[$v])) {
 $path.=self::$_SGLOBAL[&#39;URL_DELIMITER&#39;] . $get[$v];
unset($get[$v]);
}
}
}
}
 if (!$inroute) {
 if (isset($pathinfo[&#39;path&#39;])) {
 list($module, $action) = explode(&#39;/&#39;, $pathinfo[&#39;path&#39;]);
 $module = $module ? $module : self::$_SGLOBAL[&#39;DEFAULT_MODULE&#39;];
 $action = $action ? $action : self::$_SGLOBAL[&#39;DEFAULT_ACTION&#39;];
 } else {
 $module = self::$_SGLOBAL[&#39;DEFAULT_MODULE&#39;];
 $action = self::$_SGLOBAL[&#39;DEFAULT_ACTION&#39;];
}
 $path ="/$module". self::$_SGLOBAL[&#39;URL_DELIMITER&#39;] . $action;
}
 if (!empty($get)) {
 foreach ($get as $k => $v) {
 $path.=self::$_SGLOBAL[&#39;URL_DELIMITER&#39;] . $k . self::$_SGLOBAL[&#39;URL_DELIMITER&#39;] . $v;
}
}
//url伪静态
 if (self::$_SGLOBAL[&#39;URL_HTML_SUFFIX&#39;]) {
$path.=self::$_SGLOBAL[&#39;URL_HTML_SUFFIX&#39;];
}
 } elseif (self::$_SGLOBAL[&#39;URL_MODEL&#39;] == 0) {
 $url = parse_url($url);
 if (isset($url[&#39;path&#39;])) {
 list($module, $action) = explode(&#39;/&#39;, $url[&#39;path&#39;]);
 $module = $module ? $module : self::$_SGLOBAL[&#39;DEFAULT_MODULE&#39;];
 $action = $action ? $action : self::$_SGLOBAL[&#39;DEFAULT_ACTION&#39;];
 } else {
 $module = self::$_SGLOBAL[&#39;DEFAULT_MODULE&#39;];
 $action = self::$_SGLOBAL[&#39;DEFAULT_ACTION&#39;];
}
$path.="?m=$module&a=$action";
 if ($url[&#39;query&#39;]) {
 $path.=&#39;&&#39; . $url[&#39;query&#39;];
}
}
 if (!self::$_SGLOBAL[&#39;URL_REWRITE&#39;])
 $path = &#39;/&#39; . self::$_SGLOBAL[&#39;ENTRY_INDEX&#39;] . $path;
 return $path;
}

/**
 * 初始化配置信息
*/
 private static function initConfig() {
 if (defined(&#39;APP_PATH&#39;)) {
//默认模块目录
 self::$_SGLOBAL[&#39;MODULE_PATH&#39;] = APP_PATH . &#39;/action&#39;;
}
 self::$_SGLOBAL[&#39;DEFAULT_ACTION&#39;] = &#39;index&#39;; //默认action
 self::$_SGLOBAL[&#39;DEFAULT_MODULE&#39;] = &#39;Index&#39;; //默认module
//默认url路由模式,1:pathinfo模式,0为普通模式
 self::$_SGLOBAL[&#39;URL_MODEL&#39;] = 1;
 self::$_SGLOBAL[&#39;URL_DELIMITER&#39;] = &#39;/&#39;; //参数分隔符
 self::$_SGLOBAL[&#39;ENTRY_INDEX&#39;] = &#39;index.php&#39;;
 self::$_SGLOBAL[&#39;URL_HTML_SUFFIX&#39;] = null; //url伪静态
 self::$_SGLOBAL[&#39;URL_REWRITE&#39;] = false; //URL重写
 self::$_SGLOBAL[&#39;starttime&#39;] = microtime(true);
 self::$_SGLOBAL[&#39;URL_ROUTER_ON&#39;] = false; //是否启用路由功能
 self::$_SGLOBAL[&#39;DEBUG&#39;] = false;
}

/**
 * 设置选项条件,可设置的有
 * MODULE_PATH=>查找模块目录的位置
 * DEFAULT_MODULE=>默认Module
 * DEFAULT_ACTION=>默认Action
 * DEBUG=>开启调试(true|false)
 * URL_DELIMITER=>参数分隔符
 * URL_MODEL=>路由模式(0:普通模式,1:pathinfo模式)
 * URL_HTML_SUFFIX=>&#39;文件后缀&#39; pathinfo模式伪静态使用
 * ENTRY_INDEX=>入口文件
 * URL_ROUTER_ON=>开启自定义路由
 * @param array $option 选项
*/
 public function setOption($option) {
 $o = array(&#39;MODULE_PATH&#39;, &#39;DEFAULT_MODULE&#39;,
 &#39;DEFAULT_ACTION&#39;, &#39;DEBUG&#39;,
 &#39;URL_DELIMITER&#39;, &#39;URL_MODEL&#39;,
 &#39;URL_HTML_SUFFIX&#39;, &#39;ENTRY_INDEX&#39;, &#39;URL_REWRITE&#39;, &#39;URL_ROUTER_ON&#39;);
 foreach ($option as $k => $v) {
 if (in_array($k, $o)) {
 self::$_SGLOBAL[$k] = $v;
}
}
}

/**
 * 设置路由
 * array(&#39;route&#39;=>array(&#39;模块名称&#39;, &#39;操作名称&#39;,&#39;参数1,参数2,参数3&#39;))
 * @param array $route 路由
*/
 public function setRoute($route) {
 self::$route = $route;
}

}

?>


<?php

include &#39;action/CommonAction.class.php&#39;;
require &#39;mvc/Dispatcher.class.php&#39;;
require &#39;mvc/Template.class.php&#39;;

$dispatcher = Dispatcher::getInstance();

//控制器选项
$option = array(&#39;DEBUG&#39; => 1,
 &#39;URL_MODEL&#39; => 1,
 &#39;URL_DELIMITER&#39; => &#39;/&#39;,
 &#39;DEFAULT_ACTION&#39; => &#39;home&#39;,
 &#39;URL_REWRITE&#39; => 1,
 &#39;URL_ROUTER_ON&#39; => true,
&#39;URL_HTML_SUFFIX&#39;=>&#39;.html&#39;);

//自定义泛路由
$router = array(&#39;space&#39;=>array(&#39;Space&#39;, &#39;index&#39;,&#39;uid&#39;));

$dispatcher->setOption($option);
$dispatcher->setRoute($router);

Template::setU($dispatcher);
Template::setReal(true);
Template::setTemplateDir(&#39;template/default&#39;);
Template::setTmpDir(&#39;runtime/tpl&#39;);
$dispatcher->run();
?>

               


           


Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Article précédent:很简单的一个socket客户端类Article suivant:采集 PHP