From 5d41c7219fb1f8803a2fba1fc6bc0c41faf436af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=91=E6=9E=97?= Date: Fri, 7 Apr 2023 18:23:27 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8F=98=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ActiveQuery.php | 524 ++++++++++++++++----------------- Condition/DefaultCondition.php | 2 +- Condition/HashCondition.php | 9 +- Condition/InCondition.php | 4 +- Condition/NotInCondition.php | 3 +- Condition/OrCondition.php | 2 +- SqlBuilder.php | 11 +- Traits/Builder.php | 80 ++--- Traits/QueryTrait.php | 32 +- 9 files changed, 339 insertions(+), 328 deletions(-) diff --git a/ActiveQuery.php b/ActiveQuery.php index 5153a08..311b666 100644 --- a/ActiveQuery.php +++ b/ActiveQuery.php @@ -21,95 +21,95 @@ use Kiri\Abstracts\Component; class ActiveQuery extends Component implements ISqlBuilder { - use QueryTrait; + use QueryTrait; - /** @var array */ - public array $with = []; + /** @var array */ + public array $with = []; - /** @var bool */ - public bool $asArray = FALSE; + /** @var bool */ + public bool $asArray = FALSE; - /** @var bool */ - public bool $useCache = FALSE; + /** @var bool */ + public bool $useCache = FALSE; - /** - * @var Connection|null - */ - public ?Connection $db = NULL; + /** + * @var Connection|null + */ + public ?Connection $db = NULL; - /** - * @var array - * 参数绑定 - */ - public array $attributes = []; + /** + * @var array + * 参数绑定 + */ + public array $attributes = []; - /** - * Comply constructor. - * @param $model - * @param array $config - * @throws - */ - public function __construct($model, array $config = []) - { - $this->modelClass = $model; + /** + * Comply constructor. + * @param $model + * @param array $config + * @throws + */ + public function __construct($model, array $config = []) + { + $this->modelClass = $model; - $this->builder = SqlBuilder::builder($this); - parent::__construct($config); - } + $this->builder = SqlBuilder::builder($this); + parent::__construct($config); + } - /** - * 清除不完整数据 - */ - public function clear() - { - $this->db = NULL; - $this->useCache = FALSE; - $this->with = []; - } + /** + * 清除不完整数据 + */ + public function clear() + { + $this->db = NULL; + $this->useCache = FALSE; + $this->with = []; + } - /** - * @param $key - * @param $value - * @return $this - */ - public function addParam($key, $value): static - { - $this->attributes[$key] = $value; - return $this; - } + /** + * @param $key + * @param $value + * @return $this + */ + public function addParam($key, $value): static + { + $this->attributes[$key] = $value; + return $this; + } - /** - * @param int $size - * @param int $page - * @return array - * @throws - */ - #[ArrayShape([])] - public function pagination(int $size = 20, int $page = 1): array - { - $page = max(1, $page); - $size = max(1, $size); + /** + * @param int $size + * @param int $page + * @return array + * @throws + */ + #[ArrayShape([])] + public function pagination(int $size = 20, int $page = 1): array + { + $page = max(1, $page); + $size = max(1, $size); + + $offset = ($page - 1) * $size; + + $count = $this->count(); + $lists = $this->limit($offset, $size)->get()->toArray(); + return [ + 'code' => 0, + 'message' => 'ok', + 'size' => $size, + 'page' => $page, + 'count' => $count, + 'next' => max($page + 1, 1), + 'prev' => max($page - 1, 1), + 'param' => $lists, + ]; + } - $offset = ($page - 1) * $size; - $count = $this->count(); - $lists = $this->limit($offset, $size)->get()->toArray(); - return [ - 'code' => 0, - 'message' => 'ok', - 'size' => $size, - 'page' => $page, - 'count' => $count, - 'next' => max($page + 1, 1), - 'prev' => max($page - 1, 1), - 'param' => $lists, - ]; - } - - /** * @param bool $asArray * @return static @@ -121,226 +121,224 @@ class ActiveQuery extends Component implements ISqlBuilder } - /** - * @param array $values - * @return $this - */ - public function addParams(array $values): static - { - foreach ($values as $key => $val) { - $this->addParam($key, $val); - } - return $this; - } + /** + * @param array $values + * @return $this + */ + public function addParams(array $values): static + { + foreach ($values as $key => $val) { + $this->addParam($key, $val); + } + return $this; + } /** * @param array $name * @return $this */ - public function with(array $name): static - { - foreach ($name as $val) { - $this->with[] = $val; - } - return $this; - } + public function with(array $name): static + { + foreach ($name as $val) { + $this->with[] = $val; + } + return $this; + } - /** - * @param $sql - * @param array $params - * @return mixed - * @throws - */ - public function execute($sql, array $params = []): Command - { - return $this->modelClass->getConnection()->createCommand($sql, $params); - } - - - - /** - * @return ModelInterface|null - * @throws - */ - public function first(): ModelInterface|null - { - $data = $this->execute($this->builder->one())->one(); - if (is_array($data)) { - return $this->populate($data); - } else { - return NULL; - } - } + /** + * @param $sql + * @param array $params + * @return mixed + * @throws + */ + public function execute($sql, array $params = []): Command + { + return $this->modelClass->getConnection()->createCommand($sql, $params); + } - /** - * @return string - * @throws - */ - public function toSql(): string - { - return $this->builder->get(); - } + /** + * @return ModelInterface|null + * @throws + */ + public function first(): ModelInterface|null + { + $data = $this->limit(0, 1)->execute($this->builder->one(), $this->attributes)->one(); + if (is_array($data)) { + return $this->populate($data); + } else { + return NULL; + } + } - /** - * @return array|Collection - */ - public function get(): Collection|array - { - return $this->all(); - } + /** + * @return string + * @throws + */ + public function toSql(): string + { + return $this->builder->get(); + } - /** - * @throws - */ - public function flush(): array|bool|int|string|null - { - return $this->execute($this->builder->truncate())->exec(); - } + /** + * @return array|Collection + */ + public function get(): Collection|array + { + return $this->all(); + } - /** - * @param int $size - * @param callable $callback - * @param int $offset - * @return Pagination - * @throws - */ - public function page(int $size, callable $callback, int $offset = 0): Pagination - { - $pagination = new Pagination($this); - $pagination->setOffset($offset); - $pagination->setLimit($size); - $pagination->setCallback($callback); - return $pagination; - } - - /** - * @param string $field - * @param string $setKey - * - * @return array|null - * @throws - */ - public function column(string $field, string $setKey = ''): ?array - { - return $this->all()->column($field, $setKey); - } + /** + * @throws + */ + public function flush(): array|bool|int|string|null + { + return $this->execute($this->builder->truncate())->exec(); + } + /** + * @param int $size + * @param callable $callback + * @param int $offset + * @return Pagination + * @throws + */ + public function page(int $size, callable $callback, int $offset = 0): Pagination + { + $pagination = new Pagination($this); + $pagination->setOffset($offset); + $pagination->setLimit($size); + $pagination->setCallback($callback); + return $pagination; + } - /** - * @return array|Collection - * @throws - */ - public function all(): Collection|array - { - if (!($data = $this->execute($this->builder->all())->all())) { - return new Collection($this, [], $this->modelClass); - } - - $this->getWith($this->modelClass); - $collect = new Collection($this, $data, $this->modelClass); - - return $this->asArray ? $collect->toArray() : $collect; - } - - /** - * @param $data - * @return ModelInterface - * @throws - */ - public function populate($data): ModelInterface - { - return $this->getWith($this->modelClass::populate($data)); - } + /** + * @param string $field + * @param string $setKey + * + * @return array|null + * @throws + */ + public function column(string $field, string $setKey = ''): ?array + { + return $this->all()->column($field, $setKey); + } - /** - * @param ModelInterface $model - * @return ModelInterface - */ - public function getWith(ModelInterface $model): ModelInterface - { - return $model->setWith($this->with); - } + /** + * @return array|Collection + * @throws + */ + public function all(): Collection|array + { + if (!($data = $this->execute($this->builder->all())->all())) { + return new Collection($this, [], $this->modelClass); + } - /** - * @return int - * @throws - */ - public function count(): int - { - $data = $this->execute($this->builder->count())->one(); - if ($data && is_array($data)) { - return (int)array_shift($data); - } - return 0; - } + $this->getWith($this->modelClass); + $collect = new Collection($this, $data, $this->modelClass); + + return $this->asArray ? $collect->toArray() : $collect; + } + + /** + * @param $data + * @return ModelInterface + * @throws + */ + public function populate($data): ModelInterface + { + return $this->getWith($this->modelClass::populate($data)); + } - /** - * @param array $data - * @return bool - * @throws - */ - public function update(array $data): bool - { - $generate = $this->builder->update($data); - if (is_bool($generate)) { - return $generate; - } - return (bool)$this->execute(...$generate)->exec(); - } + /** + * @param ModelInterface $model + * @return ModelInterface + */ + public function getWith(ModelInterface $model): ModelInterface + { + return $model->setWith($this->with); + } - /** - * @param array $data - * @return bool - * @throws - */ - public function insert(array $data): bool - { - [$sql, $params] = $this->builder->insert($data, TRUE); + /** + * @return int + * @throws + */ + public function count(): int + { + $data = $this->execute($this->builder->count())->one(); + if ($data && is_array($data)) { + return (int)array_shift($data); + } + return 0; + } - return (bool)$this->execute($sql, $params)->exec(); - } + /** + * @param array $data + * @return bool + * @throws + */ + public function update(array $data): bool + { + $generate = $this->builder->update($data); + if (is_bool($generate)) { + return $generate; + } + return (bool)$this->execute(...$generate)->exec(); + } + + /** + * @param array $data + * @return bool + * @throws + */ + public function insert(array $data): bool + { + [$sql, $params] = $this->builder->insert($data, TRUE); + + + return (bool)$this->execute($sql, $params)->exec(); + } + + /** + * @param $filed + * + * @return null + * @throws + */ + public function value($filed) + { + return $this->first()[$filed] ?? NULL; + } + + /** + * @return bool + * @throws + */ + public function exists(): bool + { + return !empty($this->execute($this->builder->one())->fetchColumn()); + } - /** - * @param $filed - * - * @return null - * @throws - */ - public function value($filed) - { - return $this->first()[$filed] ?? NULL; - } - /** - * @return bool - * @throws - */ - public function exists(): bool - { - return !empty($this->execute($this->builder->one())->fetchColumn()); - } - - /** * @param bool $getSql * @return bool|string * @throws Exception */ - public function delete(bool $getSql = FALSE): bool|string - { - $sql = $this->builder->delete(); - if ($getSql === FALSE) { - return (bool)$this->execute($sql)->delete(); - } - return $sql; - } + public function delete(bool $getSql = FALSE): bool|string + { + $sql = $this->builder->delete(); + if ($getSql === FALSE) { + return (bool)$this->execute($sql)->delete(); + } + return $sql; + } } diff --git a/Condition/DefaultCondition.php b/Condition/DefaultCondition.php index a141e13..995304f 100644 --- a/Condition/DefaultCondition.php +++ b/Condition/DefaultCondition.php @@ -18,7 +18,7 @@ class DefaultCondition extends Condition */ #[Pure] public function builder(): string { - return sprintf('%s %s %s', $this->column, $this->opera, addslashes($this->value)); + return $this->column . ' ' . $this->opera . ' ' . addslashes($this->value); } } diff --git a/Condition/HashCondition.php b/Condition/HashCondition.php index 8b6ad75..830581a 100644 --- a/Condition/HashCondition.php +++ b/Condition/HashCondition.php @@ -12,17 +12,16 @@ class HashCondition extends Condition /** * @return string + * @throws \Exception */ public function builder(): string { $array = []; - if (empty($this->value)) { - return ''; + if (count($this->value) < 1) { + throw new \Exception('Builder data by a empty array.'); } foreach ($this->value as $key => $value) { - if (is_null($value)) continue; - - $array[] = sprintf("%s = '%s'", $key, addslashes($value)); + $array[] = $key . '=' . addslashes($value); } return implode(' AND ', $array); } diff --git a/Condition/InCondition.php b/Condition/InCondition.php index 96cc155..be9c4f0 100644 --- a/Condition/InCondition.php +++ b/Condition/InCondition.php @@ -22,9 +22,9 @@ class InCondition extends Condition #[Pure] public function builder(): string { if (is_array($this->value)) { - return sprintf('%s IN (%s)', $this->column, implode(',', $this->value)); + return $this->column . ' IN (' . implode(',', $this->value) . ')'; } else { - return sprintf('%s IN (%s)', $this->column, $this->value); + return $this->column . ' IN (' . $this->value . ')'; } } diff --git a/Condition/NotInCondition.php b/Condition/NotInCondition.php index 3d5acf7..4537833 100644 --- a/Condition/NotInCondition.php +++ b/Condition/NotInCondition.php @@ -15,11 +15,12 @@ class NotInCondition extends Condition /** * @return string|null + * @throws \Exception */ #[Pure] public function builder(): ?string { if (!is_array($this->value)) { - return null; + throw new \Exception('Builder data by a empty string. need array'); } $value = '\'' . implode('\',\'', $this->value) . '\''; return '`' . $this->column . '` not in(' . $value . ')'; diff --git a/Condition/OrCondition.php b/Condition/OrCondition.php index 065958b..825e1bc 100644 --- a/Condition/OrCondition.php +++ b/Condition/OrCondition.php @@ -21,7 +21,7 @@ class OrCondition extends Condition */ #[Pure] public function builder(): string { - return sprintf('(%s) OR %s', implode(' AND ', $this->oldParams), addslashes($this->value)); + return '(' . implode(' AND ', $this->oldParams) . ') OR ' . addslashes($this->value); } } diff --git a/SqlBuilder.php b/SqlBuilder.php index 89f49fe..dd20a1b 100644 --- a/SqlBuilder.php +++ b/SqlBuilder.php @@ -203,7 +203,6 @@ class SqlBuilder extends Component */ public function one(): string { - $this->query->limit(0, 1); return $this->_selectPrefix() . $this->_prefix() . $this->builderLimit($this->query); } @@ -321,14 +320,14 @@ class SqlBuilder extends Component */ public function tableName(): string { + if ($this->query->from === null) { + return $this->query->modelClass->getTable(); + } if ($this->query->from instanceof \Closure) { - $this->query->from = '(' . $this->query->makeClosureFunction($this->query->from) . ')'; + return $this->query->from = '(' . $this->query->makeClosureFunction($this->query->from) . ')'; } if ($this->query->from instanceof ActiveQuery) { - $this->query->from = '(' . SqlBuilder::builder($this->query->from)->get($this->query->from) . ')'; - } - if ($this->query->from == "") { - return $this->query->modelClass->getTable(); + return $this->query->from = '(' . SqlBuilder::builder($this->query->from)->get($this->query->from) . ')'; } else { return $this->query->from; } diff --git a/Traits/Builder.php b/Traits/Builder.php index ccf7e57..f26a49f 100644 --- a/Traits/Builder.php +++ b/Traits/Builder.php @@ -22,8 +22,8 @@ use ReflectionException; */ trait Builder { - - + + /** * @param $alias * @return string @@ -32,7 +32,7 @@ trait Builder { return " AS " . $alias; } - + /** * @param $table * @return string @@ -45,7 +45,7 @@ trait Builder } return " FROM " . $table; } - + /** * @param $join * @return string @@ -57,8 +57,8 @@ trait Builder } return ''; } - - + + /** * @param string $select * @return string @@ -67,8 +67,8 @@ trait Builder { return "SELECT " . $select; } - - + + /** * @param $group * @return string @@ -80,7 +80,7 @@ trait Builder } return ' GROUP BY ' . $group; } - + /** * @param $order * @return string @@ -93,7 +93,7 @@ trait Builder return ''; } } - + /** * @param ActiveQuery|Query $query * @param bool $hasLimit @@ -107,33 +107,31 @@ trait Builder return ' LIMIT ' . $query->limit; } } - - + + /** - * @param $where + * @param array $where * @return string - * @throws Exception + * @throws NotFindClassException + * @throws ReflectionException */ - private function where($where): string + private function where(array $where): string { - $_tmp = []; - if (empty($where)) return ''; - if (is_string($where)) return $where; - foreach ($where as $key => $value) { - if (is_null($value)) continue; - if (($_value = $this->resolveCondition($key, $value, $_tmp)) == '') { - continue; - } - $_tmp[] = $_value; + if (count($where) < 1) { + return ''; } - if (!empty($_tmp)) { + $_tmp = []; + foreach ($where as $key => $value) { + $_tmp[] = $this->resolveCondition($key, $value, $_tmp); + } + if (count($_tmp) > 0) { return implode(' AND ', $_tmp); } else { return ''; } } - - + + /** * @param $field * @param $condition @@ -152,8 +150,8 @@ trait Builder return $this->_arrayMap($condition, $_tmp); } } - - + + /** * @param $condition * @param $array @@ -176,10 +174,10 @@ trait Builder $builder->oldParams = $array; } else if (isset(ConditionClassMap::$conditionMap[$stroppier])) { $defaultConfig = ConditionClassMap::$conditionMap[$stroppier]; - + $class = $defaultConfig['class']; unset($defaultConfig['class']); - + $builder = Kiri::getDi()->make($class, [], $defaultConfig); $builder->setValue($condition[2]); $builder->setColumn($condition[1]); @@ -187,13 +185,16 @@ trait Builder $builder = Kiri::getDi()->get(HashCondition::class); $builder->setValue($condition); } - + $array[] = $builder->builder(); - + return implode(' AND ', $array); } - - + + + public array $params = []; + + /** * @param $condition * @return array @@ -202,16 +203,15 @@ trait Builder { $_array = []; foreach ($condition as $key => $value) { - if (is_null($value)) continue; - $value = is_numeric($value) ? $value : '\'' . $value . '\''; if (!is_numeric($key)) { - $_array[] = $key . '=' . $value; + $this->query->bindParam(':' . $key, $value); + $_array[] = $key . '=:' . $key; } else { $_array[] = $value; } } return $_array; } - - + + } diff --git a/Traits/QueryTrait.php b/Traits/QueryTrait.php index 105bd3a..ebf447c 100644 --- a/Traits/QueryTrait.php +++ b/Traits/QueryTrait.php @@ -34,7 +34,7 @@ trait QueryTrait public int $offset = 0; public int $limit = 500; public string $group = ''; - public string|Closure|ActiveQuery|null $from = ''; + public string|Closure|ActiveQuery|null $from = null; public string $alias = 't1'; public array $filter = []; @@ -757,7 +757,9 @@ trait QueryTrait return $this; } - $this->where[] = $column . ' BETWEEN ' . $start . ' AND ' . $end; + $this->bindParam(':between_start' . $column, $start); + $this->bindParam(':between_end' . $column, $end); + $this->where[] = $column . ' BETWEEN :not_between_start' . $column . ' AND :not_between_end' . $column; return $this; } @@ -774,7 +776,9 @@ trait QueryTrait return $this; } - $this->where[] = $column . 'NOT BETWEEN' . $start . ' AND ' . $end; + $this->bindParam(':not_between_start' . $column, $start); + $this->bindParam(':not_between_end' . $column, $end); + $this->where[] = $column . ' NOT BETWEEN :not_between_start' . $column . ' AND :not_between_end' . $column; return $this; } @@ -786,13 +790,24 @@ trait QueryTrait */ public function bindParams(?array $params = []): static { - if (empty($params)) { + if ($params === null) { return $this; } $this->attributes = $params; return $this; } + /** + * @param string $key + * @param mixed $value + * @return $this + */ + public function bindParam(string $key, mixed $value): static + { + $this->attributes[$key] = $value; + return $this; + } + /** * @param array|string $column * @param string $opera @@ -809,7 +824,8 @@ trait QueryTrait $this->where[] = $column; } else { [$column, $opera, $value] = $this->opera(...func_get_args()); - $this->where[] = "$column $opera $value"; + $this->bindParam(':' . $column, $value); + $this->where[] = $column . ' ' . $opera . ':' . $column; } return $this; } @@ -900,10 +916,8 @@ trait QueryTrait */ private function sprintf($column, $value, string $opera = '='): string { - if (is_string($value)) { - $value = addslashes($value); - } - return $column . ' ' . $opera . ' \'' . $value . '\''; + $this->bindParam(':' . $column, $value); + return $column . ' ' . $opera . ' :' . $column; }