From 1e47a34920e694c9efc7ae6663eb9f4cc48bcc9d Mon Sep 17 00:00:00 2001 From: topnuomi <1130395124@qq.com> Date: Thu, 30 Jul 2020 15:01:01 +0800 Subject: [PATCH] =?UTF-8?q?=E6=A8=A1=E6=9D=BF=E6=94=AF=E6=8C=81=E7=82=B9?= =?UTF-8?q?=E8=AF=AD=E6=B3=95=E3=80=81=E6=96=B0=E5=A2=9Eempty/notempty/eq/?= =?UTF-8?q?neq=E6=A0=87=E7=AD=BE=E3=80=81=E6=94=AF=E6=8C=81=E5=9C=A8?= =?UTF-8?q?=E8=87=AA=E5=AE=9A=E4=B9=89=E6=A0=87=E7=AD=BE=E6=9B=BF=E6=8D=A2?= =?UTF-8?q?=E5=86=85=E5=AE=B9=E4=B8=AD=E4=BD=BF=E7=94=A8=E6=A8=A1=E6=9D=BF?= =?UTF-8?q?=E6=A0=87=E7=AD=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- framework/library/Model.php | 25 ++- framework/library/model/Data.php | 193 ++++++++++++++++++ framework/library/template/TagLib.php | 30 +++ .../library/template/driver/engine/Engine.php | 114 ++++++++--- .../library/template/driver/engine/Tags.php | 66 +++++- 5 files changed, 392 insertions(+), 36 deletions(-) create mode 100644 framework/library/model/Data.php create mode 100644 framework/library/template/TagLib.php diff --git a/framework/library/Model.php b/framework/library/Model.php index 8404a99..5bff797 100644 --- a/framework/library/Model.php +++ b/framework/library/Model.php @@ -4,6 +4,7 @@ namespace top\library; use Exception; use top\library\exception\DatabaseException; +use top\library\model\Data; /** * 基础模型 @@ -11,10 +12,10 @@ use top\library\exception\DatabaseException; * * @method $this alias($name) * @method $this distinct(bool $distinct) - * @method $this field(string|array $field) + * @method $this field(string | array $field) * @method $this where($field, $condition = null, $value = null) * @method $this order(string $order) - * @method $this limit(string|array $limit) + * @method $this limit(string | array $limit) * @method $this join(string $table, string $on, string $type = null) * @method $this sql() */ @@ -83,6 +84,12 @@ class Model */ private $isInsert = false; + /** + * 当前查询到的数据 + * @var array + */ + private $data = []; + /** * 用数据库配置获取实例 * Model constructor. @@ -250,9 +257,9 @@ class Model /** * 查询单条记录 - * @param string|bool $param + * @param bool $param * @param bool $notRaw - * @return array + * @return Data */ public function find($param = false, $notRaw = true) { @@ -262,14 +269,14 @@ class Model $result = $this->outHandle($result); } } - return $result; + return new Data($result); } /** * 查询所有记录 - * @param string|bool $param + * @param bool $param * @param bool $notRaw - * @return array + * @return Data */ public function select($param = false, $notRaw = true) { @@ -279,7 +286,7 @@ class Model $result = $this->outHandle($result); } } - return $result; + return new Data($result); } /** @@ -596,7 +603,7 @@ class Model return call_user_func_array([$this, $methodName], $arguments); } else throw new Exception('不存在的方法:' . $name); } - + /** * 静态调用连贯操作 * @param string $name diff --git a/framework/library/model/Data.php b/framework/library/model/Data.php new file mode 100644 index 0000000..d997649 --- /dev/null +++ b/framework/library/model/Data.php @@ -0,0 +1,193 @@ +data = $data; + } + + /** + * 获取$this->>data中的值 + * @param $key + * @return mixed|null + */ + private function getValue($key) + { + if (isset($this->data[$key]) && array_key_exists($key, $this->data)) { + return $this->data[$key]; + } + return false; + } + + /** + * 外部获取$this->data中的值 + * @param $key + * @return mixed|null + */ + public function value($key) + { + return $this->getValue($key); + } + + /** + * 将字段当做属性调用 + * @param $name + * @return mixed|null + */ + public function __get($name) + { + return $this->getValue($name); + } + + /** + * Whether a offset exists + * @link https://php.net/manual/en/arrayaccess.offsetexists.php + * @param mixed $offset

+ * An offset to check for. + *

+ * @return boolean true on success or false on failure. + *

+ *

+ * The return value will be casted to boolean if non-boolean was returned. + * @since 5.0.0 + */ + public function offsetExists($offset) + { + return false !== $this->getValue($offset); + } + + /** + * Offset to retrieve + * @link https://php.net/manual/en/arrayaccess.offsetget.php + * @param mixed $offset

+ * The offset to retrieve. + *

+ * @return mixed Can return all value types. + * @since 5.0.0 + */ + public function offsetGet($offset) + { + if ($this->offsetExists($offset)) { + return $this->getValue($offset); + } + trigger_error('不存在的数组索引:' . $offset); + } + + /** + * Offset to set + * @link https://php.net/manual/en/arrayaccess.offsetset.php + * @param mixed $offset

+ * The offset to assign the value to. + *

+ * @param mixed $value

+ * The value to set. + *

+ * @return void + * @since 5.0.0 + */ + public function offsetSet($offset, $value) + { + $this->data[$offset] = $value; + } + + /** + * Offset to unset + * @link https://php.net/manual/en/arrayaccess.offsetunset.php + * @param mixed $offset

+ * The offset to unset. + *

+ * @return void + * @since 5.0.0 + */ + public function offsetUnset($offset) + { + unset($this->data[$offset]); + } + + /** + * Return the current element + * @link https://php.net/manual/en/iterator.current.php + * @return mixed Can return any type. + * @since 5.0.0 + */ + public function current() + { + return current($this->data); + } + + /** + * Move forward to next element + * @link https://php.net/manual/en/iterator.next.php + * @return void Any returned value is ignored. + * @since 5.0.0 + */ + public function next() + { + return next($this->data); + } + + /** + * Return the key of the current element + * @link https://php.net/manual/en/iterator.key.php + * @return mixed scalar on success, or null on failure. + * @since 5.0.0 + */ + public function key() + { + return key($this->data); + } + + /** + * Checks if current position is valid + * @link https://php.net/manual/en/iterator.valid.php + * @return boolean The return value will be casted to boolean and then evaluated. + * Returns true on success or false on failure. + * @since 5.0.0 + */ + public function valid() + { + return $this->current() !== false; + } + + /** + * Rewind the Iterator to the first element + * @link https://php.net/manual/en/iterator.rewind.php + * @return void Any returned value is ignored. + * @since 5.0.0 + */ + public function rewind() + { + reset($this->data); + } + + /** + * 转数组 + * @return array + */ + public function toArray() + { + return $this->data; + } + + /** + * 转JSON + * @return string + */ + public function toJson() + { + return json_encode($this->data, JSON_UNESCAPED_UNICODE); + } + +} diff --git a/framework/library/template/TagLib.php b/framework/library/template/TagLib.php new file mode 100644 index 0000000..66370b0 --- /dev/null +++ b/framework/library/template/TagLib.php @@ -0,0 +1,30 @@ +'; - /** - * @var array 标签定义 - */ - protected $tags = []; - /** * @var array 模板配置 */ - protected $config = []; + private $config = []; /** * @var array 标签库 @@ -80,8 +80,8 @@ class Engine $extendFileContent = file_get_contents($file); } // 处理继承中的include标签 - $tempContent = $this->parseInclude($extendFileContent); - $extendFileContent = $tempContent !== false ? $tempContent : $extendFileContent; + // $tempContent = $this->parseInclude($extendFileContent); + // $extendFileContent = $tempContent !== false ? $tempContent : $extendFileContent; // 被继承模板中的块 preg_match_all($blockPattern, $extendFileContent, $extendResult); // 继承模板中的块 @@ -140,13 +140,12 @@ class Engine /** * 检测是否含有include * @param $template - * @return bool + * @return int|false */ private function hasInclude($template) { $pattern = '/' . $this->left . 'include\s+file[\s\S]*?=[\s\S]*?[\'"](.*?)[\'"][\s\S]*?\/' . $this->right . '/is'; - preg_match($pattern, $template, $matches); - return !empty($matches); + return preg_match($pattern, $template, $matches); } /** @@ -162,21 +161,83 @@ class Engine for ($i = 0; $i < count($matches[0]); $i++) { $start = mb_substr($matches[1][$i], 0, 1, 'utf8'); $end = mb_substr($matches[1][$i], -1, null, 'utf8'); - $search[] = $matches[0][$i]; - if ($start == ':') { // 调用函数 + if ($start == '$') { // 输出变量 + $search[] = $matches[0][$i]; + $output = $this->parseParameterOutput($matches[1][$i]); + $replace[] = ''; + } elseif ($start == ':') { // 调用函数 + $search[] = $matches[0][$i]; $replace[] = ''; } elseif ($start == '@') { // 输出常量 - $replace[] = ''; + $search[] = $matches[0][$i]; + $replace[] = ''; } elseif ($start == '*' && $end == '*') { // 注释 + $search[] = $matches[0][$i]; $replace[] = ''; - } else { // 输出变量 - $replace[] = ''; } } - $template = str_replace($search, $replace, $template); + if (!empty($search) && !empty($replace)) { + $template = str_replace($search, $replace, $template); + } + return $template; } + /** + * 解析变量输出 + * @param $output + * @return string + */ + private function parseParameterOutput($output) + { + // 处理|函数调用 + if (strstr($output, '|')) { + $functions = explode('|', $output); + $parse = $functions[0]; + // 只留下函数表达式 + unset($functions[0]); + // 重置调用函数数组索引以便开始foreach循环 + $functions = array_values($functions); + foreach ($functions as $function) { + $expParameters = explode('=', $function); + $functionName = $expParameters[0]; + // 如果有带上参数,则进行参数处理,没有声明参数则直接将当前值作为函数的第一个参数 + if (isset($expParameters[1])) { + $parameters = $expParameters[1]; + // 如果有参数,则处理,同时将占位符###替换为上次解析结果 + // 如果存在占位符,则直接替换,没有占位符则将当前值作为函数的第一个参数 + if (strstr($expParameters[1], '###')) { + $parse = $functionName . '(' . str_replace('###', $parse, $parameters) . ')'; + } else { + $parse = $functionName . '(' . $parse . ',' . $parameters . ')'; + } + } else { + $parse = $functionName . '(' . $parse . ')'; + } + } + $output = $parse; + } + + return $this->parseDotSyntax($output); + } + + /** + * 处理.语法 + * @param $string + * @return null|string|string[] + */ + private function parseDotSyntax($string) + { + // 处理.语法(仅数组或已实现数组访问接口的对象) + return preg_replace_callback("/\.([a-zA-Z0-9_-]*)/", function ($match) { + if (isset($match[1])) { + return '[' . (is_numeric($match[1]) ? $match[1] : '\'' . $match[1] . '\'') . ']'; + } else { + return null; + } + }, $string); + } + /** * 外部加载扩展标签 * @param $prefix @@ -225,8 +286,7 @@ class Engine if (method_exists($this->libInstance[$tagInfo[0]], '_' . $tagInfo[1])) { return $this->libInstance[$tagInfo[0]]->{'_' . $tagInfo[1]}($attr, $content); } - } - // 否则尝试默认标签处理 + } // 否则尝试默认标签处理 else if (method_exists($this->libInstance['default'], '_' . $name)) { return $this->libInstance['default']->{'_' . $name}($attr, $content); } @@ -235,7 +295,6 @@ class Engine /** * 进行标签处理 * @param $template - * @param $tags * @return null|string|string[] */ private function parseTags($template) @@ -276,8 +335,9 @@ class Engine // 得到准备替换的值 $replace = explode($cut, $this->getTagParseResult($name, $attr, $cut)); $replace = [ - (isset($replace[0])) ? $replace[0] : [], - (isset($replace[1])) ? $replace[1] : [], + // 递归解析标签,使之可以在自定义标签中嵌套标签 + (isset($replace[0])) ? $this->parseTags($replace[0]) : '', + (isset($replace[1])) ? $replace[1] : '', ]; while ($startArray) { $begin = end($startArray); @@ -314,7 +374,7 @@ class Engine }, $template); } } - return preg_replace('/\?>([\r|\n|\s]*?)<\?php/is', '', $template); + return $template; } /** @@ -364,7 +424,7 @@ class Engine * @param $template * @return mixed */ - public function returnOriginal($template) + private function returnOriginal($template) { return str_replace([ '', @@ -388,12 +448,14 @@ class Engine $template = $this->parseExtend($template); // 处理include标签 $template = $this->parseInclude($template); - // 处理变量以及函数 - $template = $this->parseVars($template); // 处理定义的标签 $template = $this->parseTags($template); + // 处理变量以及函数 + $template = $this->parseVars($template); // 还原original内容 $template = $this->returnOriginal($template); + // 清除多余开始结束标签 + $template = preg_replace('/\?>([\r|\n|\s]*?)<\?php/is', '', $template); return '' . $template; } diff --git a/framework/library/template/driver/engine/Tags.php b/framework/library/template/driver/engine/Tags.php index ffc88a5..88738ac 100644 --- a/framework/library/template/driver/engine/Tags.php +++ b/framework/library/template/driver/engine/Tags.php @@ -22,8 +22,11 @@ class Tags 'assign' => ['attr' => 'name,value', 'close' => 0], 'switch' => ['attr' => 'name', 'close' => 1], 'case' => ['attr' => 'value', 'close' => 1], + 'empty' => ['attr' => 'name', 'close' => 1], + 'notempty' => ['attr' => 'name', 'close' => 1], + 'eq' => ['attr' => 'name,value', 'close' => 1], + 'neq' => ['attr' => 'name,value', 'close' => 1], ]; - /** * php标签 @@ -162,4 +165,65 @@ class Tags } return $parse; } + + /** + * empty标签 + * @param $attr + * @param $content + * @return string + */ + public function _empty($attr, $content) + { + $parse = ""; + $parse .= $content; + $parse .= ''; + return $parse; + } + + /** + * notempty标签 + * @param $attr + * @param $content + * @return string + */ + public function _notempty($attr, $content) + { + $parse = ""; + $parse .= $content; + $parse .= ''; + return $parse; + } + + /** + * eq标签 + * @param $attr + * @param $content + * @return string + */ + public function _eq($attr, $content) + { + $name = is_numeric($attr['name']) ? $attr['name'] : "\$'{$attr['name']}'"; + $value = is_numeric($attr['value']) ? $attr['value'] : "\$'{$attr['value']}'"; + $parse = ""; + $parse .= '{' . $content . '}'; + $parse .= ''; + return $parse; + } + + /** + * neq标签 + * @param $attr + * @param $content + * @return string + */ + public function _neq($attr, $content) + { + $name = is_numeric($attr['name']) ? $attr['name'] : "\$'{$attr['name']}'"; + $value = is_numeric($attr['value']) ? $attr['value'] : "\$'{$attr['value']}'"; + $parse = ""; + $parse .= '{' . $content . '}'; + $parse .= ''; + return $parse; + } + }