PageRenderTime 57ms CodeModel.GetById 31ms RepoModel.GetById 0ms app.codeStats 0ms

/libs/system/View.php

https://github.com/monkeycraps/swoole_framework
PHP | 343 lines | 186 code | 16 blank | 141 comment | 24 complexity | 402c248fd08e8b060ac4b2ee9926a08d MD5 | raw file
  1. <?php
  2. /**
  3. * 视图类
  4. * 提供一个简单试图封装
  5. * @package SwooleSystem
  6. * @author Tianfeng.Han
  7. * @subpackage MVC
  8. */
  9. class View extends ArrayObject
  10. {
  11. protected $_var = array();
  12. protected $trace = array();
  13. protected $swoole;
  14. public $template_dir = '';
  15. public $if_pagecache = false;
  16. public $cache_life = 3600;
  17. public $show_runtime = false;
  18. function __construct($swoole)
  19. {
  20. $this->swoole = $swoole;
  21. $this->template_dir = APPSPATH.'/views/';
  22. }
  23. /**
  24. +----------------------------------------------------------
  25. * 模板变量赋值
  26. +----------------------------------------------------------
  27. * @access public
  28. +----------------------------------------------------------
  29. * @param mixed $name
  30. * @param mixed $value
  31. +----------------------------------------------------------
  32. */
  33. public function assign($name,$value='')
  34. {
  35. if(is_array($name))
  36. {
  37. $this->_var = array_merge($this->_var,$name);
  38. }elseif(is_object($name)){
  39. foreach($name as $key =>$val)
  40. {
  41. $this->_var[$key] = $val;
  42. }
  43. }else {
  44. $this->_var[$name] = $value;
  45. }
  46. }
  47. /**
  48. +----------------------------------------------------------
  49. * Trace变量赋值
  50. +----------------------------------------------------------
  51. * @access public
  52. +----------------------------------------------------------
  53. * @param mixed $name
  54. * @param mixed $value
  55. +----------------------------------------------------------
  56. */
  57. public function trace($title,$value='') {
  58. if(is_array($title)) {
  59. $this->trace = array_merge($this->trace,$title);
  60. }else {
  61. $this->trace[$title] = $value;
  62. }
  63. }
  64. /**
  65. +----------------------------------------------------------
  66. * 取得模板变量的值
  67. +----------------------------------------------------------
  68. * @access public
  69. +----------------------------------------------------------
  70. * @param string $name
  71. +----------------------------------------------------------
  72. * @return mixed
  73. +----------------------------------------------------------
  74. */
  75. public function get($name){
  76. if(isset($this->_var[$name])) {
  77. return $this->_var[$name];
  78. }else {
  79. return false;
  80. }
  81. }
  82. /**
  83. +----------------------------------------------------------
  84. * 加载模板和页面输出 可以返回输出内容
  85. +----------------------------------------------------------
  86. * @access public
  87. +----------------------------------------------------------
  88. * @param string $templateFile 模板文件名 留空为自动获取
  89. * @param string $charset 模板输出字符集
  90. * @param string $contentType 输出类型
  91. +----------------------------------------------------------
  92. * @return mixed
  93. +----------------------------------------------------------
  94. */
  95. public function display($templateFile='',$charset='',$contentType='text/html')
  96. {
  97. $this->fetch($templateFile,$charset,$contentType,true);
  98. }
  99. /**
  100. +----------------------------------------------------------
  101. * 输出布局模板
  102. +----------------------------------------------------------
  103. * @access public
  104. +----------------------------------------------------------
  105. * @param string $charset 输出编码
  106. * @param string $contentType 输出类型
  107. * @param string $display 是否直接显示
  108. +----------------------------------------------------------
  109. * @return mixed
  110. +----------------------------------------------------------
  111. */
  112. public function layout($content,$charset='',$contentType='text/html')
  113. {
  114. // 查找布局包含的页面
  115. $find = preg_match_all('/<!-- layout::(.+?)::(.+?) -->/is',$content,$matches);
  116. if($find) {
  117. for ($i=0; $i< $find; $i++) {
  118. // 读取相关的页面模板替换布局单元
  119. if(0===strpos($matches[1][$i],'$')){
  120. // 动态布局
  121. $matches[1][$i] = $this->get(substr($matches[1][$i],1));
  122. }
  123. if(0 != $matches[2][$i] ) {
  124. // 设置了布局缓存
  125. // 检查布局缓存是否有效
  126. $guid = md5($matches[1][$i]);
  127. $cache = S($guid);
  128. if($cache) {
  129. $layoutContent = $cache;
  130. }else{
  131. $layoutContent = $this->fetch($matches[1][$i],$charset,$contentType);
  132. S($guid,$layoutContent,$matches[2][$i]);
  133. }
  134. }else{
  135. $layoutContent = $this->fetch($matches[1][$i],$charset,$contentType);
  136. }
  137. $content = str_replace($matches[0][$i],$layoutContent,$content);
  138. }
  139. }
  140. return $content;
  141. }
  142. /**
  143. +----------------------------------------------------------
  144. * 加载模板和页面输出
  145. +----------------------------------------------------------
  146. * @access public
  147. +----------------------------------------------------------
  148. * @param string $templateFile 模板文件名 留空为自动获取
  149. * @param string $charset 模板输出字符集
  150. * @param string $contentType 输出类型
  151. * @param string $display 是否直接显示
  152. +----------------------------------------------------------
  153. * @return mixed
  154. +----------------------------------------------------------
  155. */
  156. public function fetch($templateFile='',$charset='',$contentType='text/html',$display=false)
  157. {
  158. $GLOBALS['_viewStartTime'] = microtime(TRUE);
  159. if(null===$templateFile) {
  160. // 使用null参数作为模版名直接返回不做任何输出
  161. return ;
  162. }
  163. if(empty($charset)) {
  164. $charset = 'utf-8';
  165. }
  166. // 网页字符编码
  167. header("Content-Type:".$contentType."; charset=".$charset);
  168. header("Cache-control: private"); //支持页面回跳
  169. //页面缓存
  170. ob_start();
  171. ob_implicit_flush(0);
  172. $this->render($templateFile);
  173. // 获取并清空缓存
  174. $content = ob_get_clean();
  175. // 布局模板解析
  176. $content = $this->layout($content,$charset,$contentType);
  177. // 输出模板文件
  178. return $this->output($content,$display);
  179. }
  180. private function render($templateFile)
  181. {
  182. extract($this->_var);
  183. $templateFile = $this->parseTemplateFile($templateFile);
  184. require($templateFile);
  185. }
  186. /**
  187. +----------------------------------------------------------
  188. * 创建静态页面
  189. +----------------------------------------------------------
  190. * @access public
  191. +----------------------------------------------------------
  192. * @htmlfile 生成的静态文件名称
  193. * @param string $templateFile 指定要调用的模板文件
  194. * 默认为空 由系统自动定位模板文件
  195. * @param string $charset 输出编码
  196. * @param string $contentType 输出类型
  197. +----------------------------------------------------------
  198. * @return string
  199. +----------------------------------------------------------
  200. */
  201. public function buildHtml($htmlfile='',$templateFile='',$charset='',$contentType='text/html') {
  202. $content = $this->fetch($templateFile,$charset,$contentType);
  203. if(empty($htmlfile)) {
  204. $htmlfile = HTML_PATH.rtrim($_SERVER['PATH_INFO'],'/').C('HTML_FILE_SUFFIX');
  205. }
  206. if(!is_dir(dirname($htmlfile))) {
  207. // 如果静态目录不存在 则创建
  208. mk_dir(dirname($htmlfile));
  209. }
  210. if(false === file_put_contents($htmlfile,$content)){
  211. throw_exception(L('_CACHE_WRITE_ERROR_'));
  212. }
  213. return $content;//readfile($htmlfile);
  214. }
  215. /**
  216. +----------------------------------------------------------
  217. * 输出模板
  218. +----------------------------------------------------------
  219. * @access protected
  220. +----------------------------------------------------------
  221. * @param string $content 模板内容
  222. * @param boolean $display 是否直接显示
  223. +----------------------------------------------------------
  224. * @return mixed
  225. +----------------------------------------------------------
  226. */
  227. protected function output($content,$display) {
  228. if($this->if_pagecache)
  229. {
  230. $pagecache = new Swoole_pageCache($this->cache_life);
  231. if($pagecache->isCached()) $pagecache->load();
  232. else $pagecache->create($content);
  233. }
  234. if($display)
  235. {
  236. $showTime = $this->showTime();
  237. echo $content;
  238. if($this->show_runtime) $this->showTrace();
  239. return null;
  240. }
  241. else return $content;
  242. }
  243. private function parseTemplateFile($templateFile)
  244. {
  245. if(''==$templateFile)
  246. {
  247. $templateFile = $this->swoole->env['mvc']['controller'].'_'.$this->swoole->env['mvc']['view'].'.html';
  248. }
  249. $templateFile = $this->template_dir.$templateFile;
  250. if(!file_exists($templateFile))
  251. {
  252. Error::info('View Error!','Template file not exists! <b>'.$templateFile.'</b>');
  253. }
  254. return $templateFile;
  255. }
  256. /**
  257. +----------------------------------------------------------
  258. * 显示运行时间、数据库操作、缓存次数、内存使用信息
  259. +----------------------------------------------------------
  260. * @access protected
  261. +----------------------------------------------------------
  262. * @return string
  263. +----------------------------------------------------------
  264. */
  265. protected function showTime()
  266. {
  267. // 显示运行时间
  268. $startTime = $this->swoole->env['runtime']['start'];
  269. $endTime = microtime(TRUE);
  270. $total_run_time = number_format(($endTime - $startTime),4);
  271. $showTime = '执行时间: '.$total_run_time.'s ';
  272. $startMem = array_sum(explode(' ',$this->swoole->env['runtime']['mem']));
  273. $endMem = array_sum(explode(' ', memory_get_usage()));
  274. $showTime .= ' | 内存占用:'. number_format(($endMem - $startMem)/1024).' kb';
  275. return $showTime;
  276. }
  277. /**
  278. +----------------------------------------------------------
  279. * 显示页面Trace信息
  280. +----------------------------------------------------------
  281. * @access protected
  282. +----------------------------------------------------------
  283. * @param string $showTime 运行时间信息
  284. +----------------------------------------------------------
  285. */
  286. public function showTrace($detail=false)
  287. {
  288. // 显示页面Trace信息 读取Trace定义文件
  289. // 定义格式 return array('当前页面'=>$_SERVER['PHP_SELF'],'通信协议'=>$_SERVER['SERVER_PROTOCOL'],...);
  290. $_trace = array();
  291. // 系统默认显示信息
  292. $this->trace('当前页面', $_SERVER['REQUEST_URI']);
  293. $this->trace('请求方法', $_SERVER['REQUEST_METHOD']);
  294. $this->trace('通信协议', $_SERVER['SERVER_PROTOCOL']);
  295. $this->trace('请求时间', date('Y-m-d H:i:s',$_SERVER['REQUEST_TIME']));
  296. $this->trace('用户代理', $_SERVER['HTTP_USER_AGENT']);
  297. if(isset($_SESSION)) $this->trace('会话ID' , session_id());
  298. $this->trace('读取数据库', $this->swoole->db->read_times.'次');
  299. $this->trace('写入数据库', $this->swoole->db->write_times.'次');
  300. $included_files = get_included_files();
  301. $this->trace('加载文件', count($included_files));
  302. $this->trace('PHP执行', $this->showTime());
  303. $_trace = array_merge($_trace,$this->trace);
  304. // 调用Trace页面模板
  305. echo <<<HTML
  306. <div id="think_page_trace" style="background:white;margin:6px;font-size:14px;border:1px dashed silver;padding:8px">
  307. <fieldset id="querybox" style="margin:5px;">
  308. <legend style="color:gray;font-weight:bold">页面Trace信息</legend>
  309. <div style="overflow:auto;height:300px;text-align:left;">
  310. HTML;
  311. foreach ($_trace as $key=>$info)
  312. {
  313. echo $key.' : '.$info.'<br/>';
  314. }
  315. if($detail)
  316. {
  317. //输出包含的文件
  318. echo '加载的文件<br/>';
  319. foreach ($included_files as $file)
  320. {
  321. echo 'require '.$file.'<br/>';
  322. }
  323. }
  324. echo "</div></fieldset> </div>";
  325. }
  326. }
  327. ?>