View.class.php 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  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. * @var tVar
  19. * @access protected
  20. */
  21. protected $tVar = array();
  22. /**
  23. * 模板主题
  24. * @var theme
  25. * @access protected
  26. */
  27. protected $theme = '';
  28. /**
  29. * 模板变量赋值
  30. * @access public
  31. * @param mixed $name
  32. * @param mixed $value
  33. */
  34. public function assign($name,$value=''){
  35. if(is_array($name)) {
  36. $this->tVar = array_merge($this->tVar,$name);
  37. }else {
  38. $this->tVar[$name] = $value;
  39. }
  40. }
  41. /**
  42. * 取得模板变量的值
  43. * @access public
  44. * @param string $name
  45. * @return mixed
  46. */
  47. public function get($name=''){
  48. if('' === $name) {
  49. return $this->tVar;
  50. }
  51. return isset($this->tVar[$name])?$this->tVar[$name]:false;
  52. }
  53. /**
  54. * 加载模板和页面输出 可以返回输出内容
  55. * @access public
  56. * @param string $templateFile 模板文件名
  57. * @param string $charset 模板输出字符集
  58. * @param string $contentType 输出类型
  59. * @param string $content 模板输出内容
  60. * @param string $prefix 模板缓存前缀
  61. * @return mixed
  62. */
  63. public function display($templateFile='',$charset='',$contentType='',$content='',$prefix='') {
  64. G('viewStartTime');
  65. // 视图开始标签
  66. Hook::listen('view_begin',$templateFile);
  67. // 解析并获取模板内容
  68. $content = $this->fetch($templateFile,$content,$prefix);
  69. // 输出模板内容
  70. $this->render($content,$charset,$contentType);
  71. // 视图结束标签
  72. Hook::listen('view_end');
  73. }
  74. /**
  75. * 输出内容文本可以包括Html
  76. * @access private
  77. * @param string $content 输出内容
  78. * @param string $charset 模板输出字符集
  79. * @param string $contentType 输出类型
  80. * @return mixed
  81. */
  82. private function render($content,$charset='',$contentType=''){
  83. if(empty($charset)) $charset = C('DEFAULT_CHARSET');
  84. if(empty($contentType)) $contentType = C('TMPL_CONTENT_TYPE');
  85. // 网页字符编码
  86. header('Content-Type:'.$contentType.'; charset='.$charset);
  87. header('Cache-control: '.C('HTTP_CACHE_CONTROL')); // 页面缓存控制
  88. header('X-Powered-By:ThinkPHP');
  89. // 输出模板文件
  90. echo $content;
  91. }
  92. /**
  93. * 解析和获取模板内容 用于输出
  94. * @access public
  95. * @param string $templateFile 模板文件名
  96. * @param string $content 模板输出内容
  97. * @param string $prefix 模板缓存前缀
  98. * @return string
  99. */
  100. public function fetch($templateFile='',$content='',$prefix='') {
  101. if(empty($content)) {
  102. $templateFile = $this->parseTemplate($templateFile);
  103. // 模板文件不存在直接返回
  104. if(!is_file($templateFile)) E(L('_TEMPLATE_NOT_EXIST_').':'.$templateFile);
  105. }else{
  106. defined('THEME_PATH') or define('THEME_PATH', $this->getThemePath());
  107. }
  108. // 页面缓存
  109. ob_start();
  110. ob_implicit_flush(0);
  111. if('php' == strtolower(C('TMPL_ENGINE_TYPE'))) { // 使用PHP原生模板
  112. $_content = $content;
  113. // 模板阵列变量分解成为独立变量
  114. extract($this->tVar, EXTR_OVERWRITE);
  115. // 直接载入PHP模板
  116. empty($_content)?include $templateFile:eval('?>'.$_content);
  117. }else{
  118. // 视图解析标签
  119. $params = array('var'=>$this->tVar,'file'=>$templateFile,'content'=>$content,'prefix'=>$prefix);
  120. Hook::listen('view_parse',$params);
  121. }
  122. // 获取并清空缓存
  123. $content = ob_get_clean();
  124. // 内容过滤标签
  125. Hook::listen('view_filter',$content);
  126. // 输出模板文件
  127. return $content;
  128. }
  129. /**
  130. * 自动定位模板文件
  131. * @access protected
  132. * @param string $template 模板文件规则
  133. * @return string
  134. */
  135. public function parseTemplate($template='') {
  136. if(is_file($template)) {
  137. return $template;
  138. }
  139. $depr = C('TMPL_FILE_DEPR');
  140. $template = str_replace(':', $depr, $template);
  141. // 获取当前模块
  142. $module = MODULE_NAME;
  143. if(strpos($template,'@')){ // 跨模块调用模版文件
  144. list($module,$template) = explode('@',$template);
  145. }
  146. // 获取当前主题的模版路径
  147. defined('THEME_PATH') or define('THEME_PATH', $this->getThemePath($module));
  148. // 分析模板文件规则
  149. if('' == $template) {
  150. // 如果模板文件名为空 按照默认规则定位
  151. $template = CONTROLLER_NAME . $depr . ACTION_NAME;
  152. }elseif(false === strpos($template, $depr)){
  153. $template = CONTROLLER_NAME . $depr . $template;
  154. }
  155. $file = THEME_PATH.$template.C('TMPL_TEMPLATE_SUFFIX');
  156. if(C('TMPL_LOAD_DEFAULTTHEME') && THEME_NAME != C('DEFAULT_THEME') && !is_file($file)){
  157. // 找不到当前主题模板的时候定位默认主题中的模板
  158. $file = dirname(THEME_PATH).'/'.C('DEFAULT_THEME').'/'.$template.C('TMPL_TEMPLATE_SUFFIX');
  159. }
  160. return $file;
  161. }
  162. /**
  163. * 获取当前的模板路径
  164. * @access protected
  165. * @param string $module 模块名
  166. * @return string
  167. */
  168. protected function getThemePath($module=MODULE_NAME){
  169. // 获取当前主题名称
  170. $theme = $this->getTemplateTheme();
  171. // 获取当前主题的模版路径
  172. $tmplPath = C('VIEW_PATH'); // 模块设置独立的视图目录
  173. if(!$tmplPath){
  174. // 定义TMPL_PATH 则改变全局的视图目录到模块之外
  175. $tmplPath = defined('TMPL_PATH')? TMPL_PATH.$module.'/' : APP_PATH.$module.'/'.C('DEFAULT_V_LAYER').'/';
  176. }
  177. return $tmplPath.$theme;
  178. }
  179. /**
  180. * 设置当前输出的模板主题
  181. * @access public
  182. * @param mixed $theme 主题名称
  183. * @return View
  184. */
  185. public function theme($theme){
  186. $this->theme = $theme;
  187. return $this;
  188. }
  189. /**
  190. * 获取当前的模板主题
  191. * @access private
  192. * @return string
  193. */
  194. private function getTemplateTheme() {
  195. if($this->theme) { // 指定模板主题
  196. $theme = $this->theme;
  197. }else{
  198. /* 获取模板主题名称 */
  199. $theme = C('DEFAULT_THEME');
  200. if(C('TMPL_DETECT_THEME')) {// 自动侦测模板主题
  201. $t = C('VAR_TEMPLATE');
  202. if (isset($_GET[$t])){
  203. $theme = $_GET[$t];
  204. }elseif(cookie('think_template')){
  205. $theme = cookie('think_template');
  206. }
  207. if(!in_array($theme,explode(',',C('THEME_LIST')))){
  208. $theme = C('DEFAULT_THEME');
  209. }
  210. cookie('think_template',$theme,864000);
  211. }
  212. }
  213. defined('THEME_NAME') || define('THEME_NAME', $theme); // 当前模板主题名称
  214. return $theme?$theme . '/':'';
  215. }
  216. }