From c2ef6cc883ab88042d9e8d9c876115b2f56b641d Mon Sep 17 00:00:00 2001 From: thinkphp Date: Mon, 18 Apr 2016 15:32:18 +0800 Subject: [PATCH] =?UTF-8?q?View=E7=B1=BB=E5=92=8C=E6=A8=A1=E6=9D=BF?= =?UTF-8?q?=E5=BC=95=E6=93=8E=E9=A9=B1=E5=8A=A8=E5=88=86=E7=A6=BB=E8=B0=83?= =?UTF-8?q?=E6=95=B4=20=E6=A8=A1=E6=9D=BF=E4=B8=BB=E9=A2=98=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E5=8F=96=E6=B6=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- convention.php | 16 +++ library/think/Controller.php | 6 +- library/think/Template.php | 41 ++++---- library/think/View.php | 156 +++------------------------- library/think/view/driver/Php.php | 106 +++++++++++++++++++ library/think/view/driver/Think.php | 75 ++++++++++++- 6 files changed, 231 insertions(+), 169 deletions(-) create mode 100644 library/think/view/driver/Php.php diff --git a/convention.php b/convention.php index d4d94782..9d86e2f6 100644 --- a/convention.php +++ b/convention.php @@ -98,6 +98,22 @@ return [ // | 视图及模板设置 // +---------------------------------------------------------------------- + 'view' => [ + // 模板引擎 + 'engine_type' => 'think', + // 模板引擎配置 + 'engine_config' => [ + // 模板路径 + 'view_path' => '', + // 模板后缀 + 'view_suffix' => '.html', + // 模板文件名分隔符 + 'view_depr' => DS, + ], + // 输出字符串替换 + 'parse_str' => [], + ], + // 默认跳转页面对应的模板文件 'dispatch_success_tmpl' => THINK_PATH . 'tpl' . DS . 'dispatch_jump.tpl', 'dispatch_error_tmpl' => THINK_PATH . 'tpl' . DS . 'dispatch_jump.tpl', diff --git a/library/think/Controller.php b/library/think/Controller.php index cd60e4be..9f58fc27 100644 --- a/library/think/Controller.php +++ b/library/think/Controller.php @@ -13,6 +13,8 @@ namespace think; \think\Loader::import('controller/Jump', TRAIT_PATH, EXT); +use think\View; + class Controller { use \traits\controller\Jump; @@ -33,7 +35,7 @@ class Controller */ public function __construct() { - $this->view = \think\View::instance(Config::get()); + $this->view = View::instance(Config::get('view')); // 控制器初始化 if (method_exists($this, '_initialize')) { @@ -102,7 +104,7 @@ class Controller */ public function display($template = '', $vars = [], $config = []) { - return $this->view->fetch($template, $vars, $config); + return $this->view->display($template, $vars, $config); } /** diff --git a/library/think/Template.php b/library/think/Template.php index db79043a..b9f3f32c 100644 --- a/library/think/Template.php +++ b/library/think/Template.php @@ -172,7 +172,7 @@ class Template if (!empty($this->config['cache_id']) && $this->config['display_cache']) { // 读取渲染缓存 $cacheContent = Cache::get($this->config['cache_id']); - if ($cacheContent !== false) { + if (false !== $cacheContent) { echo $cacheContent; return; } @@ -205,13 +205,17 @@ class Template * @access public * @param string $content 模板内容 * @param array $vars 模板变量 + * @param array $config 模板参数 * @return void */ - public function fetch($content, $vars = []) + public function fetch($content, $vars = [], $config = []) { if ($vars) { $this->data = $vars; } + if ($config) { + $this->config($config); + } $cacheFile = $this->config['cache_path'] . $this->config['cache_prefix'] . md5($content) . $this->config['cache_suffix']; if (!$this->checkCache($cacheFile)) { // 缓存无效 模板编译 @@ -736,31 +740,31 @@ class Template } elseif (')' == substr($name, -1, 1)) { // $name为对象或是自动识别,或者含有函数 switch ($first) { - case '?': + case '?': $str = ''; break; - case '=': + case '=': $str = ''; break; - default: + default: $str = ''; } } else { // $name为数组 switch ($first) { - case '?': + case '?': // {$varname??'xxx'} $varname有定义则输出$varname,否则输出xxx $str = ''; break; - case '=': + case '=': // {$varname?='xxx'} $varname为真时才输出xxx $str = ''; break; - case ':': + case ':': // {$varname?:'xxx'} $varname为真时输出$varname,否则输出xxx $str = ''; break; - default: + default: if (strpos($str, ':')) { // {$varname ? 'a' : 'b'} $varname为真时输出a,否则输出b $str = ''; @@ -838,13 +842,13 @@ class Template $parseStr = $this->parseThinkVar($vars); } else { switch ($this->config['tpl_var_identify']) { - case 'array': // 识别为数组 + case 'array': // 识别为数组 $parseStr = $first . '[\'' . implode('\'][\'', $vars) . '\']'; break; - case 'obj': // 识别为对象 + case 'obj': // 识别为对象 $parseStr = $first . '->' . implode('->', $vars); break; - default: // 自动判断数组或对象 + default: // 自动判断数组或对象 $parseStr = '(is_array(' . $first . ')?' . $first . '[\'' . implode('\'][\'', $vars) . '\']:' . $first . '->' . implode('->', $vars) . ')'; } } @@ -890,14 +894,14 @@ class Template // 模板函数过滤 $fun = trim($args[0]); switch ($fun) { - case 'default': // 特殊模板函数 + case 'default': // 特殊模板函数 if (false === strpos($name, '(')) { $name = '(isset(' . $name . ') && (' . $name . ' !== \'\')?' . $name . ':' . $args[1] . ')'; } else { $name = '(' . $name . ' !== \'\'?' . $name . ':' . $args[1] . ')'; } break; - default: // 通用模板函数 + default: // 通用模板函数 if (!in_array($fun, $template_deny_funs)) { if (isset($args[1])) { if (strstr($args[1], '###')) { @@ -1045,15 +1049,8 @@ class Template $template = str_replace(['/', ':'], $this->config['view_depr'], $template); $template = APP_PATH . str_replace('@', '/' . basename($this->config['view_path']) . '/', $template) . $this->config['view_suffix']; } else { - if (strpos($template, ':')) { - // 指定主题 - list($theme, $template) = explode(':', $template, 2); - $path = dirname($this->config['view_path']) . DS . $theme . DS; - } else { - $path = $this->config['view_path']; - } $template = str_replace(['/', ':'], $this->config['view_depr'], $template); - $template = $path . $template . $this->config['view_suffix']; + $template = $this->config['view_path'] . $template . $this->config['view_suffix']; } } if (is_file($template)) { diff --git a/library/think/View.php b/library/think/View.php index bbf87743..d91c699a 100644 --- a/library/think/View.php +++ b/library/think/View.php @@ -17,38 +17,22 @@ class View protected static $instance = null; // 模板引擎实例 public $engine = null; - // 模板主题名称 - protected $theme = ''; // 模板变量 protected $data = []; // 视图参数 protected $config = [ - // 模板主题 - 'theme_on' => false, - // 默认主题 开启模板主题有效 - 'default_theme' => 'default', - // 视图文件路径 - 'view_path' => '', - // 视图文件后缀 - 'view_suffix' => '.html', - // 视图文件分隔符 - 'view_depr' => DS, - // 视图层目录名 - 'view_layer' => VIEW_LAYER, // 视图输出字符串替换 'parse_str' => [], // 视图驱动命名空间 'namespace' => '\\think\\view\\driver\\', + 'engine_type' => 'think', // 模板引擎配置参数 - 'template' => [], + 'engine_config' => [], ]; public function __construct(array $config = []) { $this->config($config); - if (!isset($this->config['template']['type'])) { - $this->config['template']['type'] = 'think'; - } } /** @@ -70,7 +54,7 @@ class View * @access public * @param mixed $name 变量名 * @param mixed $value 变量值 - * @return View + * @return $this */ public function assign($name, $value = '') { @@ -88,7 +72,7 @@ class View * @access public * @param mixed $config 视图参数或者数组 * @param string $value 值 - * @return View + * @return mixed */ public function config($config = '', $value = null) { @@ -112,59 +96,21 @@ class View * @access public * @param string $engine 引擎名称 * @param array $config 引擎参数 - * @return View + * @return $this */ public function engine($engine, array $config = []) { - if ('php' == $engine) { - $this->engine = 'php'; - } else { - $class = $this->config['namespace'] . ucfirst($engine); - if (empty($this->config['view_path']) && defined('VIEW_PATH')) { - $this->config['view_path'] = VIEW_PATH; - } - - $config = array_merge($config, [ - 'view_path' => $this->config['view_path'], - 'view_suffix' => $this->config['view_suffix'], - 'view_depr' => $this->config['view_depr'], - ]); - $this->engine = new $class($config); - } - return $this; - } - - /** - * 设置当前输出的模板主题 - * @access public - * @param mixed $theme 主题名称 - * @return View - */ - public function theme($theme) - { - if (true === $theme) { - // 启用主题 - $this->config['theme_on'] = true; - } elseif (false === $theme) { - // 关闭主题 - $this->config['theme_on'] = false; - } else { - // 指定主题 - $this->config['theme_on'] = true; - $this->theme = $theme; - } + $class = $this->config['namespace'] . ucfirst($engine); + $this->engine = new $class($config); return $this; } /** * 解析和获取模板内容 用于输出 - * @access public - * * @param string $template 模板文件名或者内容 * @param array $vars 模板输出变量 * @param array $config 模板参数 * @param bool $renderContent 是否渲染内容 - * * @return string * @throws Exception */ @@ -172,32 +118,18 @@ class View { // 模板变量 $vars = array_merge($this->data, $vars); - if (!$renderContent) { - // 获取模板文件名 - $template = $this->parseTemplate($template); - // 开启调试模式Win环境严格区分大小写 - // 模板不存在 抛出异常 - if (!is_file($template) || (APP_DEBUG && IS_WIN && realpath($template) != $template)) { - throw new Exception('template file not exists:' . $template, 10700); - } - // 记录视图信息 - APP_DEBUG && Log::record('[ VIEW ] ' . $template . ' [ ' . var_export(array_keys($vars), true) . ' ]', 'info'); - } if (is_null($this->engine)) { // 初始化模板引擎 - $this->engine($this->config['template']['type'], $this->config['template']); + $this->engine($this->config['engine_type'], $this->config['engine_config']); } // 页面缓存 ob_start(); ob_implicit_flush(0); - if ('php' == $this->engine || empty($this->engine)) { - // 原生PHP解析 - extract($vars, EXTR_OVERWRITE); - is_file($template) ? include $template : eval('?>' . $template); - } else { - // 指定模板引擎 - $this->engine->fetch($template, $vars, $config); - } + + // 渲染输出 + $method = $renderContent ? 'display' : 'fetch'; + $this->engine->$method($template, $vars, $config); + // 获取并清空缓存 $content = ob_get_clean(); // 内容过滤标签 @@ -219,68 +151,12 @@ class View * @access public * @param string $content 内容 * @param array $vars 模板输出变量 + * @param array $config 模板参数 * @return mixed */ - public function show($content, $vars = []) + public function display($content, $vars = [], $config = []) { - return $this->fetch($content, $vars, '', true); - } - - /** - * 自动定位模板文件 - * @access private - * @param string $template 模板文件规则 - * @return string - */ - private function parseTemplate($template) - { - if (is_file($template)) { - return realpath($template); - } - if (empty($this->config['view_path']) && defined('VIEW_PATH')) { - $this->config['view_path'] = VIEW_PATH; - } - // 获取当前主题 - $theme = $this->getTemplateTheme(); - $this->config['view_path'] .= $theme; - - $depr = $this->config['view_depr']; - $template = str_replace(['/', ':'], $depr, $template); - if (strpos($template, '@')) { - list($module, $template) = explode('@', $template); - $path = APP_PATH . (APP_MULTI_MODULE ? $module . DS : '') . $this->config['view_layer'] . DS; - } else { - $path = $this->config['view_path']; - } - - // 分析模板文件规则 - if (defined('CONTROLLER_NAME')) { - if ('' == $template) { - // 如果模板文件名为空 按照默认规则定位 - $template = str_replace('.', DS, CONTROLLER_NAME) . $depr . ACTION_NAME; - } elseif (false === strpos($template, $depr)) { - $template = str_replace('.', DS, CONTROLLER_NAME) . $depr . $template; - } - } - return realpath($path) . DS . $template . $this->config['view_suffix']; - } - - /** - * 获取当前的模板主题 - * @access private - * @return string - */ - private function getTemplateTheme() - { - if ($this->config['theme_on']) { - if ($this->theme) { - // 指定模板主题 - $theme = $this->theme; - } else { - $theme = $this->config['default_theme']; - } - } - return isset($theme) ? $theme . DS : ''; + return $this->fetch($content, $vars, $config, true); } /** diff --git a/library/think/view/driver/Php.php b/library/think/view/driver/Php.php new file mode 100644 index 00000000..51614f30 --- /dev/null +++ b/library/think/view/driver/Php.php @@ -0,0 +1,106 @@ + +// +---------------------------------------------------------------------- +namespace think\view\driver; + +use think\Exception; +use think\Log; + +class Php +{ + // 模板引擎参数 + protected $config = [ + // 模板起始路径 + 'view_path' => '', + // 模板文件后缀 + 'view_suffix' => '.html', + // 模板文件名分隔符 + 'view_depr' => DS, + ]; + + public function __construct($config = []) + { + $this->config = array_merge($this->config, $config); + } + + /** + * 渲染模板文件 + * @access public + * @param string $template 模板文件 + * @param array $data 模板变量 + * @return void + */ + public function fetch($template, $data = []) + { + if (!is_file($template)) { + // 获取模板文件名 + $template = $this->parseTemplate($template); + } + // 模板不存在 抛出异常 + if (!is_file($template)) { + throw new Exception('template file not exists:' . $template, 10700); + } + // 记录视图信息 + APP_DEBUG && Log::record('[ VIEW ] ' . $template . ' [ ' . var_export(array_keys($data), true) . ' ]', 'info'); + extract($data, EXTR_OVERWRITE); + include $template; + } + + /** + * 渲染模板内容 + * @access public + * @param string $content 模板内容 + * @param array $data 模板变量 + * @return void + */ + public function display($content, $data = []) + { + extract($data, EXTR_OVERWRITE); + eval('?>' . $content); + } + + /** + * 自动定位模板文件 + * @access private + * @param string $template 模板文件规则 + * @return string + */ + private function parseTemplate($template) + { + if (empty($this->config['view_path']) && defined('VIEW_PATH')) { + $this->config['view_path'] = VIEW_PATH; + } + + $depr = $this->config['view_depr']; + $template = str_replace(['/', ':'], $depr, $template); + if (strpos($template, '@')) { + list($module, $template) = explode('@', $template); + $path = APP_PATH . (APP_MULTI_MODULE ? $module . DS : '') . VIEW_LAYER . DS; + } else { + $path = $this->config['view_path']; + } + + // 分析模板文件规则 + if (defined('CONTROLLER_NAME')) { + if ('' == $template) { + // 如果模板文件名为空 按照默认规则定位 + $template = str_replace('.', DS, CONTROLLER_NAME) . $depr . ACTION_NAME; + } elseif (false === strpos($template, $depr)) { + $template = str_replace('.', DS, CONTROLLER_NAME) . $depr . $template; + } + } + return realpath($path) . DS . $template . $this->config['view_suffix']; + } + + public function __call($method, $params) + { + return call_user_func_array([$this->template, $method], $params); + } +} diff --git a/library/think/view/driver/Think.php b/library/think/view/driver/Think.php index cb092c4e..d983f517 100644 --- a/library/think/view/driver/Think.php +++ b/library/think/view/driver/Think.php @@ -10,15 +10,28 @@ // +---------------------------------------------------------------------- namespace think\view\driver; +use think\Exception; +use think\Log; use think\Template; class Think { + // 模板引擎实例 private $template = null; + // 模板引擎参数 + protected $config = [ + // 模板起始路径 + 'view_path' => '', + // 模板文件后缀 + 'view_suffix' => '.html', + // 模板文件名分隔符 + 'view_depr' => DS, + ]; public function __construct($config = []) { - $this->template = new Template($config); + $this->config = array_merge($this->config, $config); + $this->template = new Template($this->config); } /** @@ -31,11 +44,63 @@ class Think */ public function fetch($template, $data = [], $config = []) { - if (is_file($template)) { - $this->template->display($template, $data, $config); - } else { - $this->template->fetch($template, $data); + if (!is_file($template)) { + // 获取模板文件名 + $template = $this->parseTemplate($template); } + // 模板不存在 抛出异常 + if (!is_file($template)) { + throw new Exception('template file not exists:' . $template, 10700); + } + // 记录视图信息 + APP_DEBUG && Log::record('[ VIEW ] ' . $template . ' [ ' . var_export(array_keys($data), true) . ' ]', 'info'); + $this->template->display($template, $data, $config); + } + + /** + * 渲染模板内容 + * @access public + * @param string $template 模板文件或者内容 + * @param array $data 模板变量 + * @param array $config 模板参数 + * @return void + */ + public function display($template, $data = [], $config = []) + { + $this->template->fetch($template, $data, $config); + } + + /** + * 自动定位模板文件 + * @access private + * @param string $template 模板文件规则 + * @return string + */ + private function parseTemplate($template) + { + if (empty($this->config['view_path']) && defined('VIEW_PATH')) { + $this->config['view_path'] = VIEW_PATH; + } + + $depr = $this->config['view_depr']; + $template = str_replace(['/', ':'], $depr, $template); + if (strpos($template, '@')) { + list($module, $template) = explode('@', $template); + $path = APP_PATH . (APP_MULTI_MODULE ? $module . DS : '') . VIEW_LAYER . DS; + } else { + $path = $this->config['view_path']; + } + + // 分析模板文件规则 + if (defined('CONTROLLER_NAME')) { + if ('' == $template) { + // 如果模板文件名为空 按照默认规则定位 + $template = str_replace('.', DS, CONTROLLER_NAME) . $depr . ACTION_NAME; + } elseif (false === strpos($template, $depr)) { + $template = str_replace('.', DS, CONTROLLER_NAME) . $depr . $template; + } + } + return realpath($path) . DS . $template . $this->config['view_suffix']; } public function __call($method, $params)