PHP文件调度器调度,MVC的调度器和模板类

本文介绍了一个PHP模板引擎的实现,包括变量赋值、条件语句、循环结构以及包含其他模板的功能。同时,文章还展示了如何实现一个URL调度器,支持不同模式的URL,如普通模式和PATHINFO模式,并且支持自定义路由和伪静态。调度器能够根据URL解析出模块和操作,加载对应的控制器执行相应操作。通过这两个组件,可以构建一个简单的MVC框架。
摘要由CSDN通过智能技术生成

调整了设置参数的的方法

新增了普通路由模式

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't to mkdir");

}

self::$tTmpDir = realpath($dir);

}

/**

* URL调度器

* @param Dispatcher $dispatcher

*/

public static function setU(&$dispatcher) {

if (is_object($dispatcher) && method_exists($dispatcher, 'U')) {

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, '.');

$tmp = 'tpl_' . substr($basename, 0, $pos) . '.php';

return self::$tTmpDir . '/' . $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('$1')", $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.='.html';

$tFile = self::$tDir ? self::$tDir . '/' . $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('<?php } elseif(\1) { ?>','')", $this->tContent);

$this->tContent = preg_replace("/{else}/is","<?php } else { ?>", $this->tContent);

$this->tContent = preg_replace("/{U((.+?))}/ies","$this->parseUrl('$1')", $this->tContent);

//循环

for ($i = 0; $i < 6; $i++) {

$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);

$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);

$this->tContent = preg_replace("/{ifs+(.+?)}(.+?){/if}/ies","$this->stripvtags('<?php if(\1) { ?>','\2<?php } ?>')", $this->tContent);

}

}

private function stripvtags($expr, $statement='') {

$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;

}

}

}

?>

/**

* 控制调度器

* 先定义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=>'文件后缀' 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['URL_MODEL'] == 1) {

$route = $this->pathInfoRoute();

} else {

$route = $this->generalRoute();

}

$modulefile = self::$_SGLOBAL['MODULE_PATH'] ."/{$route['module']}.class.php";

if (file_exists($modulefile)) {

include $modulefile;

if (class_exists($route['module'])) {

$class = new $route['module'];

if (method_exists($class, $route['action'])) {

call_user_func(array(&$class, $route['action']));

}else

die("in {$route['module']} module no this {$route['action']} action");

}else

die("no this {$route['module']} module");

}else {

die("no this {$route['module']} module");

}

self::$_SGLOBAL['endtime'] = microtime(true);

$this->debugInfo();

}

/**

* 输出调试信息

*/

private function debugInfo() {

if (self::$_SGLOBAL['DEBUG']) {

$exectime = self::$_SGLOBAL['endtime'] - self::$_SGLOBAL['starttime'];

$debuginfo = <<

.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;}

Debug Info
Execute Time$exectime s
Include File

HTML;

foreach (get_included_files () as $file) {

$debuginfo.=$file ."
";

}

$debuginfo.="

Server Info";

$debuginfo.="Host:". $_SERVER['HTTP_HOST'] ."
";

$debuginfo.="PHP_Version:". PHP_VERSION ."
";

$debuginfo.="Server_Version:". $_SERVER['SERVER_SOFTWARE'] ."
";

$debuginfo.="

$debuginfo.="

Client Info";

$debuginfo.="Remote_Addr:". $_SERVER['REMOTE_ADDR'] ."
";

$debuginfo.="User_Agent:". $_SERVER['HTTP_USER_AGENT'] ."
";

$debuginfo.="

";

$debuginfo.="

";

echo $debuginfo;

}

}

private function generalRoute() {

$route = array();

$route['module'] = !empty($_GET['m']) ? $_GET['m'] : self::$_SGLOBAL['DEFAULT_MODULE'];

$route['action'] = !empty($_GET['a']) ? $_GET['a'] : self::$_SGLOBAL['DEFAULT_ACTION'];

$route['module'].='Action';

unset($_GET['m']);

unset($_GET['a']);

return $route;

}

/**

* PATHINFO形式的路由调度

* 支持伪静态

*/

private function pathInfoRoute() {

$route = array();

//伪静态

if (self::$_SGLOBAL['URL_HTML_SUFFIX']) {

$pos = strlen($_SERVER['PATH_INFO']) - strlen(self::$_SGLOBAL['URL_HTML_SUFFIX']);

$_SERVER['PATH_INFO'] = substr($_SERVER['PATH_INFO'], 0, $pos);

}

if (!$_SERVER['PATH_INFO'] || $_SERVER['PATH_INFO'] == '/') {

$route = array('module' => self::$_SGLOBAL['DEFAULT_MODULE'],

'action' => self::$_SGLOBAL['DEFAULT_ACTION']);

} else {

$_SERVER['PATH_INFO'] = substr($_SERVER['PATH_INFO'], 1);

$pathinfo = explode(self::$_SGLOBAL['URL_DELIMITER'], $_SERVER['PATH_INFO']);

//用户自定义路由

if (self::$_SGLOBAL['URL_ROUTER_ON'] && in_array($pathinfo[0], array_keys(self::$route))) {

$route['module'] = self::$route[$pathinfo[0]][0];

$route['action'] = self::$route[$pathinfo[0]][1];

$c = explode(',', self::$route[$pathinfo[0]][2]);

array_shift($pathinfo);

foreach ($c as $r) {

$_GET[$r] = array_shift($pathinfo);

}

} else {

if (count($pathinfo) < 2) {

$route['module'] = $pathinfo[0] . self::$_SGLOBAL['MODULE_SUFFIX'];

$route['action'] = self::$_SGLOBAL['DEFAULT_ACTION'] . self::$_SGLOBAL['ACTION_SUFFIX'];

} else {

$route['module'] = array_shift($pathinfo) . self::$_SGLOBAL['MODULE_SUFFIX'];

$route['action'] = array_shift($pathinfo) . self::$_SGLOBAL['ACTION_SUFFIX'];

}

}

if (count($pathinfo) >= 2) {

for ($i = 0, $cnt = count($pathinfo); $i < $cnt; $i++) {

if (isset($pathinfo[$i + 1])) {

$_GET[$pathinfo[$i]] = $pathinfo[++$i];

}

}

}

}

$route['module'].='Action';

$_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 = '';

$get = array();

$inroute = false; //用户定义的路由

if (isset($pathinfo['query'])) {

$query = explode('&', $pathinfo['query']);

foreach ($query as $q) {

list($k, $v) = explode('=', $q);

$get[$k] = $v;

}

}

if (!self::$_SGLOBAL) {

self::initConfig();

}

//pathinfo方式的url

if (self::$_SGLOBAL['URL_MODEL'] == 1) {

if (self::$_SGLOBAL['URL_ROUTER_ON'] && strpos($pathinfo['path'], '@') !== false) {

//取出所有用户定义的路由

$routeNames = array_keys(self::$route);

$p = substr($pathinfo['path'], 0, -1);

if (in_array($p, $routeNames)) {

$inroute = true;

$path.='/' . $p;

$c = explode(',', self::$route[$p][2]);

foreach ($c as $v) {

if (isset($get[$v])) {

$path.=self::$_SGLOBAL['URL_DELIMITER'] . $get[$v];

unset($get[$v]);

}

}

}

}

if (!$inroute) {

if (isset($pathinfo['path'])) {

list($module, $action) = explode('/', $pathinfo['path']);

$module = $module ? $module : self::$_SGLOBAL['DEFAULT_MODULE'];

$action = $action ? $action : self::$_SGLOBAL['DEFAULT_ACTION'];

} else {

$module = self::$_SGLOBAL['DEFAULT_MODULE'];

$action = self::$_SGLOBAL['DEFAULT_ACTION'];

}

$path ="/$module". self::$_SGLOBAL['URL_DELIMITER'] . $action;

}

if (!empty($get)) {

foreach ($get as $k => $v) {

$path.=self::$_SGLOBAL['URL_DELIMITER'] . $k . self::$_SGLOBAL['URL_DELIMITER'] . $v;

}

}

//url伪静态

if (self::$_SGLOBAL['URL_HTML_SUFFIX']) {

$path.=self::$_SGLOBAL['URL_HTML_SUFFIX'];

}

} elseif (self::$_SGLOBAL['URL_MODEL'] == 0) {

$url = parse_url($url);

if (isset($url['path'])) {

list($module, $action) = explode('/', $url['path']);

$module = $module ? $module : self::$_SGLOBAL['DEFAULT_MODULE'];

$action = $action ? $action : self::$_SGLOBAL['DEFAULT_ACTION'];

} else {

$module = self::$_SGLOBAL['DEFAULT_MODULE'];

$action = self::$_SGLOBAL['DEFAULT_ACTION'];

}

$path.="?m=$module&a=$action";

if ($url['query']) {

$path.='&' . $url['query'];

}

}

if (!self::$_SGLOBAL['URL_REWRITE'])

$path = '/' . self::$_SGLOBAL['ENTRY_INDEX'] . $path;

return $path;

}

/**

* 初始化配置信息

*/

private static function initConfig() {

if (defined('APP_PATH')) {

//默认模块目录

self::$_SGLOBAL['MODULE_PATH'] = APP_PATH . '/action';

}

self::$_SGLOBAL['DEFAULT_ACTION'] = 'index'; //默认action

self::$_SGLOBAL['DEFAULT_MODULE'] = 'Index'; //默认module

//默认url路由模式,1:pathinfo模式,0为普通模式

self::$_SGLOBAL['URL_MODEL'] = 1;

self::$_SGLOBAL['URL_DELIMITER'] = '/'; //参数分隔符

self::$_SGLOBAL['ENTRY_INDEX'] = 'index.php';

self::$_SGLOBAL['URL_HTML_SUFFIX'] = null; //url伪静态

self::$_SGLOBAL['URL_REWRITE'] = false; //URL重写

self::$_SGLOBAL['starttime'] = microtime(true);

self::$_SGLOBAL['URL_ROUTER_ON'] = false; //是否启用路由功能

self::$_SGLOBAL['DEBUG'] = false;

}

/**

* 设置选项条件,可设置的有

* MODULE_PATH=>查找模块目录的位置

* DEFAULT_MODULE=>默认Module

* DEFAULT_ACTION=>默认Action

* DEBUG=>开启调试(true|false)

* URL_DELIMITER=>参数分隔符

* URL_MODEL=>路由模式(0:普通模式,1:pathinfo模式)

* URL_HTML_SUFFIX=>'文件后缀' pathinfo模式伪静态使用

* ENTRY_INDEX=>入口文件

* URL_ROUTER_ON=>开启自定义路由

* @param array $option 选项

*/

public function setOption($option) {

$o = array('MODULE_PATH', 'DEFAULT_MODULE',

'DEFAULT_ACTION', 'DEBUG',

'URL_DELIMITER', 'URL_MODEL',

'URL_HTML_SUFFIX', 'ENTRY_INDEX', 'URL_REWRITE', 'URL_ROUTER_ON');

foreach ($option as $k => $v) {

if (in_array($k, $o)) {

self::$_SGLOBAL[$k] = $v;

}

}

}

/**

* 设置路由

* array('route'=>array('模块名称', '操作名称','参数1,参数2,参数3'))

* @param array $route 路由

*/

public function setRoute($route) {

self::$route = $route;

}

}

?>

include 'action/CommonAction.class.php';

require 'mvc/Dispatcher.class.php';

require 'mvc/Template.class.php';

$dispatcher = Dispatcher::getInstance();

//控制器选项

$option = array('DEBUG' => 1,

'URL_MODEL' => 1,

'URL_DELIMITER' => '/',

'DEFAULT_ACTION' => 'home',

'URL_REWRITE' => 1,

'URL_ROUTER_ON' => true,

'URL_HTML_SUFFIX'=>'.html');

//自定义泛路由

$router = array('space'=>array('Space', 'index','uid'));

$dispatcher->setOption($option);

$dispatcher->setRoute($router);

Template::setU($dispatcher);

Template::setReal(true);

Template::setTemplateDir('template/default');

Template::setTmpDir('runtime/tpl');

$dispatcher->run();

?>

本文原创发布php中文网,转载请注明出处,感谢您的尊重!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值