View.class.php 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2006-2014 http://thinkphp.cn All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
  8. // +----------------------------------------------------------------------
  9. // | Author: liu21st <liu21st@gmail.com>
  10. // +----------------------------------------------------------------------
  11. namespace Think;
  12. /**
  13. * ThinkPHP 视图类
  14. */
  15. class View
  16. {
  17. /**
  18. * 模板输出变量
  19. * @var tVar
  20. * @access protected
  21. */
  22. protected $tVar = array();
  23. /**
  24. * 模板主题
  25. * @var theme
  26. * @access protected
  27. */
  28. protected $theme = '';
  29. /**
  30. * 模板变量赋值
  31. * @access public
  32. * @param mixed $name
  33. * @param mixed $value
  34. */
  35. public function assign($name, $value = '')
  36. {
  37. if (is_array($name)) {
  38. $this->tVar = array_merge($this->tVar, $name);
  39. } else {
  40. $this->tVar[$name] = $value;
  41. }
  42. }
  43. /**
  44. * 取得模板变量的值
  45. * @access public
  46. * @param string $name
  47. * @return mixed
  48. */
  49. public function get($name = '')
  50. {
  51. if ('' === $name) {
  52. return $this->tVar;
  53. }
  54. return isset($this->tVar[$name]) ? $this->tVar[$name] : false;
  55. }
  56. /**
  57. * 加载模板和页面输出 可以返回输出内容
  58. * @access public
  59. * @param string $templateFile 模板文件名
  60. * @param string $charset 模板输出字符集
  61. * @param string $contentType 输出类型
  62. * @param string $content 模板输出内容
  63. * @param string $prefix 模板缓存前缀
  64. * @return mixed
  65. */
  66. public function display($templateFile = '', $charset = '', $contentType = '', $content = '', $prefix = '')
  67. {
  68. G('viewStartTime');
  69. // 视图开始标签
  70. Hook::listen('view_begin', $templateFile);
  71. // 解析并获取模板内容
  72. $content = $this->fetch($templateFile, $content, $prefix);
  73. // 输出模板内容
  74. $this->render($content, $charset, $contentType);
  75. // 视图结束标签
  76. Hook::listen('view_end');
  77. }
  78. /**
  79. * 输出内容文本可以包括Html
  80. * @access private
  81. * @param string $content 输出内容
  82. * @param string $charset 模板输出字符集
  83. * @param string $contentType 输出类型
  84. * @return mixed
  85. */
  86. private function render($content, $charset = '', $contentType = '')
  87. {
  88. if (empty($charset)) {
  89. $charset = C('DEFAULT_CHARSET');
  90. }
  91. if (empty($contentType)) {
  92. $contentType = C('TMPL_CONTENT_TYPE');
  93. }
  94. // 网页字符编码
  95. header('Content-Type:' . $contentType . '; charset=' . $charset);
  96. header('Cache-control: ' . C('HTTP_CACHE_CONTROL')); // 页面缓存控制
  97. header('X-Powered-By:OpenCMF');
  98. // 输出模板文件
  99. echo $content;
  100. }
  101. /**
  102. * 解析和获取模板内容 用于输出
  103. * @access public
  104. * @param string $templateFile 模板文件名
  105. * @param string $content 模板输出内容
  106. * @param string $prefix 模板缓存前缀
  107. * @return string
  108. */
  109. public function fetch($templateFile = '', $content = '', $prefix = '')
  110. {
  111. if (empty($content)) {
  112. $templateFile = $this->parseTemplate($templateFile);
  113. // 模板文件不存在直接返回
  114. if (!is_file($templateFile)) {
  115. E(L('_TEMPLATE_NOT_EXIST_') . ':' . $templateFile);
  116. }
  117. } else {
  118. defined('THEME_PATH') or define('THEME_PATH', $this->getThemePath());
  119. }
  120. // 页面缓存
  121. ob_start();
  122. ob_implicit_flush(0);
  123. if ('php' == strtolower(C('TMPL_ENGINE_TYPE'))) {
  124. // 使用PHP原生模板
  125. if (empty($content)) {
  126. if (isset($this->tVar['templateFile'])) {
  127. $__template__ = $templateFile;
  128. extract($this->tVar, EXTR_OVERWRITE);
  129. include $__template__;
  130. } else {
  131. extract($this->tVar, EXTR_OVERWRITE);
  132. include $templateFile;
  133. }
  134. } elseif (isset($this->tVar['content'])) {
  135. $__content__ = $content;
  136. extract($this->tVar, EXTR_OVERWRITE);
  137. eval('?>' . $__content__);
  138. } else {
  139. extract($this->tVar, EXTR_OVERWRITE);
  140. eval('?>' . $content);
  141. }
  142. } else {
  143. // 视图解析标签
  144. $params = array('var' => $this->tVar, 'file' => $templateFile, 'content' => $content, 'prefix' => $prefix);
  145. Hook::listen('view_parse', $params);
  146. }
  147. // 获取并清空缓存
  148. $content = ob_get_clean();
  149. // 内容过滤标签
  150. Hook::listen('view_filter', $content);
  151. if (APP_DEBUG && C('PARSE_VAR')) {
  152. // debug模式时,将后台分配变量输出到浏览器控制台
  153. $parseVar = empty($this->tVar) ? json_encode(array()) : json_encode($this->tVar);
  154. $content = $content . '<script type="text/javascript">var PARSE_VAR = ' . $parseVar . ';</script>';
  155. }
  156. // 输出模板文件
  157. return $content;
  158. }
  159. /**
  160. * 自动定位模板文件
  161. * @access protected
  162. * @param string $template 模板文件规则
  163. * @return string
  164. */
  165. public function parseTemplate($template = '')
  166. {
  167. if (is_file($template)) {
  168. return $template;
  169. }
  170. $depr = C('TMPL_FILE_DEPR');
  171. $template = str_replace(':', $depr, $template);
  172. // 获取当前模块
  173. $module = MODULE_NAME;
  174. if (strpos($template, '@')) {
  175. // 跨模块调用模版文件
  176. list($module, $template) = explode('@', $template);
  177. }
  178. // 获取当前主题的模版路径
  179. defined('THEME_PATH') or define('THEME_PATH', $this->getThemePath($module));
  180. // 分析模板文件规则
  181. if ('' == $template) {
  182. // 如果模板文件名为空 按照默认规则定位
  183. $template = CONTROLLER_NAME . $depr . ACTION_NAME;
  184. } elseif (false === strpos($template, $depr)) {
  185. $template = CONTROLLER_NAME . $depr . $template;
  186. }
  187. $file = THEME_PATH . $template . C('TMPL_TEMPLATE_SUFFIX');
  188. if (C('TMPL_LOAD_DEFAULTTHEME') && THEME_NAME != C('DEFAULT_THEME') && !is_file($file)) {
  189. // 找不到当前主题模板的时候定位默认主题中的模板
  190. $file = dirname(THEME_PATH) . '/' . C('DEFAULT_THEME') . '/' . $template . C('TMPL_TEMPLATE_SUFFIX');
  191. }
  192. return $file;
  193. }
  194. /**
  195. * 获取当前的模板路径
  196. * @access protected
  197. * @param string $module 模块名
  198. * @return string
  199. */
  200. protected function getThemePath($module = MODULE_NAME)
  201. {
  202. // 获取当前主题名称
  203. $theme = $this->getTemplateTheme();
  204. // 获取当前主题的模版路径
  205. $tmplPath = C('VIEW_PATH'); // 模块设置独立的视图目录
  206. if (!$tmplPath) {
  207. // 定义TMPL_PATH 则改变全局的视图目录到模块之外
  208. $tmplPath = defined('TMPL_PATH') ? TMPL_PATH . $module . '/' : APP_PATH . $module . '/' . C('DEFAULT_V_LAYER') . '/';
  209. }
  210. return $tmplPath . $theme;
  211. }
  212. /**
  213. * 设置当前输出的模板主题
  214. * @access public
  215. * @param mixed $theme 主题名称
  216. * @return View
  217. */
  218. public function theme($theme)
  219. {
  220. $this->theme = $theme;
  221. return $this;
  222. }
  223. /**
  224. * 获取当前的模板主题
  225. * @access private
  226. * @return string
  227. */
  228. private function getTemplateTheme()
  229. {
  230. if ($this->theme) {
  231. // 指定模板主题
  232. $theme = $this->theme;
  233. } else {
  234. /* 获取模板主题名称 */
  235. $theme = C('DEFAULT_THEME');
  236. if (C('TMPL_DETECT_THEME')) {
  237. // 自动侦测模板主题
  238. $t = C('VAR_TEMPLATE');
  239. if (isset($_GET[$t])) {
  240. $theme = $_GET[$t];
  241. } elseif (cookie('think_template')) {
  242. $theme = cookie('think_template');
  243. }
  244. if (!in_array($theme, explode(',', C('THEME_LIST')))) {
  245. $theme = C('DEFAULT_THEME');
  246. }
  247. cookie('think_template', $theme, 864000);
  248. }
  249. }
  250. defined('THEME_NAME') || define('THEME_NAME', $theme); // 当前模板主题名称
  251. return $theme ? $theme . '/' : '';
  252. }
  253. }