From a2e2602c59c7a6e7d16b78e4a4cd3dbd29a1f617 Mon Sep 17 00:00:00 2001 From: topnuomi <1130395124@qq.com> Date: Sun, 28 Jul 2019 16:06:38 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=8A=A0=E8=BD=BD=E8=87=AA?= =?UTF-8?q?=E5=AE=9A=E4=B9=89=E6=A0=87=E7=AD=BE=E5=BA=93=E7=9A=84=E6=96=B9?= =?UTF-8?q?=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...hp => 2ec7facf63614beb8c7f02cc2378e1cd.php | 4 +- demo/index.html | 4 + script.php | 25 +- template/Engine.php | 346 +++++++++--------- template/Extend.php | 8 +- 5 files changed, 194 insertions(+), 193 deletions(-) rename aa7cc8f2dc7ba35fd85943e9db00190b.php => 2ec7facf63614beb8c7f02cc2378e1cd.php (66%) diff --git a/aa7cc8f2dc7ba35fd85943e9db00190b.php b/2ec7facf63614beb8c7f02cc2378e1cd.php similarity index 66% rename from aa7cc8f2dc7ba35fd85943e9db00190b.php rename to 2ec7facf63614beb8c7f02cc2378e1cd.php index 5688f9f..60952c6 100644 --- a/aa7cc8f2dc7ba35fd85943e9db00190b.php +++ b/2ec7facf63614beb8c7f02cc2378e1cd.php @@ -6,14 +6,14 @@ - + 将上面的内容放入raw标签: {$vo} - + 扩展的标签: diff --git a/demo/index.html b/demo/index.html index 439f66b..bcb1431 100644 --- a/demo/index.html +++ b/demo/index.html @@ -12,8 +12,12 @@ {$vo} + {$a} {:time()} + + {:time()} + 扩展的标签: diff --git a/script.php b/script.php index a3b74d3..5dfe2b9 100644 --- a/script.php +++ b/script.php @@ -3,24 +3,15 @@ require 'template/Engine.php'; require 'template/Extend.php'; $content = file_get_contents('./demo/index.html'); - -echo "\r\n\r\n原始内容\r\n\r\n"; -print_r($content); - -$template = new \template\Engine(); -// 默认编译结果 +$t1 = microtime(true); +$template = \template\Engine::instance(); +// 加载自定义标签库 +$template->loadTaglib(\template\Extend::class); +// 编译 $result = $template->compile($content); - -echo "\r\n\r\n第一次结果\r\n\r\n"; -print_r($result); - -// 开始处理用户定义标签库 -$extend = new \template\Extend(); -$result = $extend->parseCustomizeTags($result); -// 用户定义标签库处理结束 - // 最后还原raw标签 $result = $template->returnRaw($result); +$t2 = microtime(true); +echo '执行时间' . ($t2 - $t1) . "\r\n"; -echo "\r\n\r\n第二次结果\r\n\r\n"; -print_r($result); +file_put_contents(md5(time()) . '.php', $result); \ No newline at end of file diff --git a/template/Engine.php b/template/Engine.php index 8d0e4ea..3c8bbdc 100644 --- a/template/Engine.php +++ b/template/Engine.php @@ -9,6 +9,12 @@ namespace template; */ class Engine { + + /** + * @var null 单一实例 + */ + private static $instance = null; + /** * @var string 左定界符 */ @@ -28,23 +34,26 @@ class Engine * @var null 模板配置 */ protected $config = null; - + /** - * @var null 模板路径 + * @var null 扩展标签库 */ - private $viewDir = null; + private $extend = []; + + /** + * @var array 扩展标签库类实例 + */ + private $extendInstance = []; /** * @var array 默认标签定义 */ private $defaultTags = [ + 'php' => ['attr' => null, 'close' => 1], 'if' => ['attr' => 'condition', 'close' => 1], 'else' => ['attr' => 'condition', 'close' => 0], 'volist' => ['attr' => 'name,id,key', 'close' => 1], - 'assign' => ['attr' => 'name,value', 'close' => 0], - 'switch' => ['attr' => 'name', 'close' => 1], - 'case' => ['attr' => 'value', 'close' => 1], - 'default' => ['attr' => '', 'close' => 1] + 'assign' => ['attr' => 'name,value', 'close' => 0] ]; /** @@ -52,24 +61,44 @@ class Engine * Engine constructor. * @throws \Exception */ - public function __construct() + private function __construct() { - // 仅作示例,请在外部传入模板目录 - $this->viewDir = './demo/'; + // $this->config = Register::get('Config')->get('view'); + $this->config['dir'] = './demo/'; + if (isset($this->config['left']) && $this->config['left']) { + $this->left = $this->config['left']; + } + if (isset($this->config['right']) && $this->config['right']) { + $this->right = $this->config['right']; + } + } + + /** + * 获取类单一实例 + * @return null|Engine + */ + public static function instance() + { + if (!self::$instance) { + self::$instance = new self(); + } + return self::$instance; } /** * 处理模板继承 + * @param $template + * @return mixed */ - private function parseExtend($tmpl) + private function parseExtend($template) { $pattern = '#' . $this->left . 'extend +file=[\'"](.*?)[\'"] +/' . $this->right . '#'; - preg_match($pattern, $tmpl, $matches); + preg_match($pattern, $template, $matches); if (!empty($matches)) { $blockPattern = '#' . $this->left . 'block +name=[\'"](.*?)[\'"]' . $this->right; $blockPattern .= '([\s\S]*?)' . $this->left . '\/block' . $this->right . '#'; // 获得被继承的模板内容 - $file = $this->viewDir . $matches[1] . '.html'; + $file = $this->config['dir'] . $matches[1] . '.html'; $extendFileContent = null; if (file_exists($file)) { $extendFileContent = file_get_contents($file); @@ -80,7 +109,7 @@ class Engine // 被继承模板中的块 preg_match_all($blockPattern, $extendFileContent, $extendResult); // 继承模板中的块 - preg_match_all($blockPattern, $tmpl, $templateResult); + preg_match_all($blockPattern, $template, $templateResult); // 组合搜索的块数组 $search = []; $defaultContent = []; @@ -104,172 +133,219 @@ class Engine $replaceArray[] = $defaultContent[$key]; } } - $tmpl = str_replace($searchArray, $replaceArray, $extendFileContent); + $template = str_replace($searchArray, $replaceArray, $extendFileContent); } - return $tmpl; + return $template; } /** * 处理include标签 - * @return bool + * @param $template + * @return null|string|string[] */ - private function parseInclude($tmpl) + private function parseInclude($template) { $pattern = '#' . $this->left . 'include +file=[\'"](.*?)[\'"] +/' . $this->right . '#'; - $tmpl = preg_replace_callback($pattern, function ($result) { + $template = preg_replace_callback($pattern, function ($result) { $str = null; - $file = $this->viewDir . $result[1] . '.html'; + $file = $this->config['dir'] . $result[1] . '.html'; if (file_exists($file)) { $str = file_get_contents($file); } return $str; - }, $tmpl); + }, $template); // 处理多层include - if ($this->hasInclude($tmpl)) { - $tmpl = $this->parseInclude($tmpl); + if ($this->hasInclude($template)) { + $template = $this->parseInclude($template); } - return $tmpl; + return $template; } /** * 检测是否含有include - * @param $tmpl + * @param $template * @return bool */ - private function hasInclude($tmpl) + private function hasInclude($template) { $pattern = '#' . $this->left . 'include +file=[\'"](.*?)[\'"] +/' . $this->right . '#'; - preg_match($pattern, $tmpl, $matches); + preg_match($pattern, $template, $matches); return !empty($matches); } /** * 分析参数以及函数输出 + * @param $template + * @return mixed */ - private function parseVars($tmpl) + private function parseVars($template) { - preg_match_all('#{(.*?)}#', $tmpl, $matches); + preg_match_all('#{(.*?)}#', $template, $matches); $search = []; $replace = []; for ($i = 0; $i < count($matches[0]); $i++) { $start = substr($matches[1][$i], 0, 1); + $search[] = $matches[0][$i]; if ($start == '$') { - $search[] = $matches[0][$i]; - $replace[] = ''; + $replace[] = ''; } elseif ($start == ':') { - $search[] = $matches[0][$i]; - $replace[] = ''; + $replace[] = ''; + } else { + $replace[] = $matches[0][$i]; } } - $tmpl = str_replace($search, $replace, $tmpl); - return $tmpl; + $template = str_replace($search, $replace, $template); + return $template; } /** - * 处理用户自定义标签 - * @param $tmpl - * @return null|string|string[] + * 外部加载扩展标签 + * @param $lib */ - public function parseCustomizeTags($tmpl) + public function loadTaglib($lib) { - return $this->parseTags($tmpl, $this->tags); + $this->extend[] = $lib; } /** - * 处理默认的标签 - * @param $tmpl + * 标签处理 + * @param $template * @return null|string|string[] */ - private function parseDefaultTags($tmpl) + private function parseTags($template) { - return $this->parseTags($tmpl, $this->defaultTags); + foreach ($this->extend as $lib) { + $this->extendInstance[$lib] = $object = new $lib; + foreach ($object->tags as $name => $tag) { + if (!isset($this->tags[$name]) && !isset($this->defaultTags[$name])) { + $this->tags[$name] = $tag; + } + } + } + $tags = array_merge($this->defaultTags, $this->tags); + return $this->_parseTags($template, $tags); + } + + /** + * 获取标签处理结果 + * @param $name + * @param $tagContent + * @return mixed + */ + private function getTagParseResult($name, $tagContent = []) + { + if (method_exists($this, $name)) { + return $this->{$name}($tagContent); + } else { + foreach ($this->extendInstance as $item) { + if (method_exists($item, $name)) { + return $item->{$name}($tagContent); + } + } + return null; + } } /** * 进行标签处理 - * @param $tmpl + * @param $template * @param $tags * @return null|string|string[] */ - private function parseTags($tmpl, $tags) + private function _parseTags($template, $tags) { foreach ($tags as $name => $item) { - $attr = ($item['attr']) ? ' +(.*?)' : null; - $pattern = '#' . $this->left . $name . $attr . ($item['close'] ? $this->right : '\/' . $this->right . '#'); - if ($item['close']) { - $pattern .= '([\s\S]*?)' . $this->left . '\/' . $name . $this->right . '#'; - } - preg_match_all($pattern, $tmpl, $matches); + $pattern = '#' . $this->left . $name . '(.*?)' . ($item['close'] ? null : '\/') . $this->right . '#'; + preg_match_all($pattern, $template, $matches); for ($i = 0; $i < count($matches[0]); $i++) { - $attrPattern = '#(.*?)=[\'"](.*?)[\'"]#'; - preg_match_all($attrPattern, $matches[1][$i], $result); $tag = []; - if (!empty($result)) { - foreach ($result[1] as $key => $value) { - $tag[trim($value, ' ')] = $result[2][$key]; + if ($item['attr']) { + $attrPattern = '#(.*?)=[\'"](.*?)[\'"]#'; + preg_match_all($attrPattern, $matches[1][$i], $result); + if (isset($result[0]) && !empty($result[0])) { + foreach ($result[1] as $key => $value) { + $tag[trim($value, ' ')] = $result[2][$key]; + } } } - if ($item['close']) { - $tagContent = isset($matches[2][$i]) ? $matches[2][$i] : (($attr) ? null : $matches[1][$i]); - $content = $this->{'_' . $name . '_start'}($tag, $tagContent); - if ($item['close']) { - $content .= $this->{'_' . $name . '_end'}($tag, $tagContent); - } - } else { - $content = $this->{'_' . $name . '_start'}($tag); - } - $tmpl = str_replace($matches[0][$i], $content, $tmpl); + $function = ($item['close']) ? '_' . $name . '_start' : '_' . $name; + $template = str_replace($matches[0][$i], $this->getTagParseResult($function, $tag), $template); + } + if ($item['close']) { + $closePattern = '#' . $this->left . '\/' . $name . $this->right . '#'; + $template = preg_replace_callback($closePattern, function () use ($name) { + $function = '_' . $name . '_end'; + return $this->getTagParseResult($function); + }, $template); } } - return preg_replace('#\?>([\r|\n|\s]*?)<\?php#', '', $tmpl); + return preg_replace('#\?>([\r|\n|\s]*?)<\?php#', '', $template); } /** * 处理raw标签 - * @param $tmpl + * @param $template * @return null|string|string[] */ - private function parseRaw($tmpl) + private function parseRaw($template) { $pattern = '#' . $this->left . 'raw' . $this->right . '([\s\S]*?)'; $pattern .= $this->left . '\/raw' . $this->right . '#'; - $tmpl = preg_replace_callback($pattern, function ($matches) { + $template = preg_replace_callback($pattern, function ($matches) { return str_replace([ $this->left, $this->right, '{', '}' ], [ '', - '{raw!--', '--raw}' + '<-raw!--', '--raw->' ], $matches[1]); - }, $tmpl); - return $tmpl; + }, $template); + return $template; } /** * 还原raw - * @param $tmpl - * @return null|string|string[] + * @param $template + * @return mixed */ - public function returnRaw($tmpl) + public function returnRaw($template) { - $pattern = '#[{|<]raw!--([\s\S]*?)--raw[>|}]#'; - $tmpl = preg_replace_callback($pattern, function ($matches) { - $left = substr($matches[0], 0, 1); - $right = substr($matches[0], -1); - return $left . $matches[1] . $right; - }, $tmpl); - return $tmpl; + $template = str_replace([ + '', + '<-raw!--', '--raw->' + ], [ + $this->left, $this->right, + '{', '}' + ], $template); + return $template; + } + + /** + * php标签开始 + * @return string + */ + private function _php_start() + { + return ''; } /** * if标签 * @param $tag - * @param $content * @return string */ - private function _if_start($tag, $content) + private function _if_start($tag) { - return '' . $content; + return ''; } /** @@ -299,10 +375,9 @@ class Engine /** * volist标签 * @param $tag - * @param $content * @return string */ - private function _volist_start($tag, $content) + private function _volist_start($tag) { if (substr($tag['name'], 0, 1) == ':') { $name = substr($tag['name'], 1); @@ -311,7 +386,7 @@ class Engine } $key = (empty($tag['key'])) ? null : '$' . $tag['key'] . ' = 0;'; $parse = '' . $content; + $parse .= ($key ? '$' . $tag['key'] . '++;' : null) . ' ?>'; return $parse; } @@ -329,99 +404,30 @@ class Engine * @param $tag * @return string */ - private function _assign_start($tag) + private function _assign($tag) { return ''; } - /** - * switch标签 - * @param $tag - * @param $content - * @return string - */ - private function _switch_start($tag, $content) - { - $parse = '' . $content; - return $parse; - } - - /** - * switch标签结束 - * @return string - */ - private function _switch_end() - { - $parse = ''; - return $parse; - } - - /** - * case标签 - * @param $tag - * @param $content - * @return string - */ - private function _case_start($tag, $content) - { - if (is_numeric($tag['value'])) { - $caseVar = $tag['value']; - } else { - $caseVar = '\'' . $tag['value'] . '\''; - } - $parse = '' . $content; - return $parse; - } - - /** - * case标签结束 - * @return string - */ - private function _case_end() - { - $parse = ''; - return $parse; - } - - /** - * default标签 - * @param $tag - * @param $content - * @return string - */ - private function _default_start($tag, $content) - { - $parse = '' . $content; - return $parse; - } - - /** - * default标签结束 - * @return string - */ - private function _default_end() - { - $parse = ''; - return $parse; - } - /** * 获取编译后的内容 - * @param $tmpl + * @param $template * @return bool|mixed|null|string|string[] */ - public function compile($tmpl) + public function compile($template) { - $tmpl = $this->parseRaw($tmpl); + // 处理raw标签 + $template = $this->parseRaw($template); // 处理模板继承标签 - $tmpl = $this->parseExtend($tmpl); + $template = $this->parseExtend($template); // 处理include标签 - $tmpl = $this->parseInclude($tmpl); + $template = $this->parseInclude($template); // 处理变量以及函数 - $tmpl = $this->parseVars($tmpl); + $template = $this->parseVars($template); // 处理定义的标签 - $tmpl = $this->parseDefaultTags($tmpl); - return $tmpl; + $template = $this->parseTags($template); + + return $template; } } diff --git a/template/Extend.php b/template/Extend.php index 77e272f..01b2a64 100644 --- a/template/Extend.php +++ b/template/Extend.php @@ -2,13 +2,13 @@ namespace template; -class Extend extends Engine +class Extend { - protected $tags = [ + public $tags = [ 'say' => ['attr' => 'what', 'close' => 0] ]; - - protected function _say_start($tag) + + public function _say($tag) { return ''; }