From 00a2125efc48eed3ba54c4db1520a449fd93b8c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=91=E6=9E=97?= Date: Mon, 31 Jul 2023 23:08:59 +0800 Subject: [PATCH] qqq --- Base/CollectionIterator.php | 1 - Base/Getter.php | 75 -- Base/Model.php | 2 +- Base/Setter.php | 80 -- Collection.php | 21 +- Command.php | 48 +- Db.php | 14 +- Model.php | 26 +- Mysql/Columns.php | 703 +++++++-------- Mysql/Schema.php | 2 +- Pagination.php | 320 +++---- SqlBuilder.php | 3 +- Traits/Builder.php | 14 +- Traits/QueryTrait.php | 1633 ++++++++++++++++------------------- Traits/When.php | 4 +- 15 files changed, 1334 insertions(+), 1612 deletions(-) delete mode 100644 Base/Getter.php delete mode 100644 Base/Setter.php diff --git a/Base/CollectionIterator.php b/Base/CollectionIterator.php index ee2f6c2..f584815 100644 --- a/Base/CollectionIterator.php +++ b/Base/CollectionIterator.php @@ -5,7 +5,6 @@ declare(strict_types=1); namespace Database\Base; -use Database\ActiveQuery; use Database\ModelInterface; use Exception; diff --git a/Base/Getter.php b/Base/Getter.php deleted file mode 100644 index 0358d42..0000000 --- a/Base/Getter.php +++ /dev/null @@ -1,75 +0,0 @@ -getter[$className])) { - $this->getter[$className] = []; - } - $this->getter[$className][$name] = $method; - } - - /** - * @param string $className - * @return array - */ - public function getAll(string $className): array - { - return $this->getter[$className] ?? []; - } - - /** - * @param string $className - * @param string $name - * @return bool - */ - public function has(string $className, string $name): bool - { - return isset($this->getter[$className]) && isset($this->getter[$className][$name]); - } - - - /** - * @param ModelInterface $class - * @param string $key - * @param mixed $value - * @return mixed - */ - public function override(ModelInterface $class, string $key, mixed $value): mixed - { - $method = $this->getter[$class::class][$key] ?? null; - if ($method !== null) { - return $class->{$method}($value); - } - return $value; - } - - /** - * @param string $className - * @param string $name - * @return string|null - */ - public function get(string $className, string $name): ?string - { - if (!$this->has($className,$name)) { - return null; - } - return $this->getter[$className][$name]; - } - -} diff --git a/Base/Model.php b/Base/Model.php index 407b3c8..7f1c1e3 100644 --- a/Base/Model.php +++ b/Base/Model.php @@ -536,7 +536,7 @@ abstract class Model extends Component implements ModelInterface, ArrayAccess, T } $validate = $this->resolve($rule); if (!$validate->validation()) { - return \Kiri::getLogger()->addError($validate->getError(), 'mysql'); + return \Kiri::getLogger()->failure($validate->getError(), 'mysql'); } else { return TRUE; } diff --git a/Base/Setter.php b/Base/Setter.php deleted file mode 100644 index f45f223..0000000 --- a/Base/Setter.php +++ /dev/null @@ -1,80 +0,0 @@ -setter[$className])) { - $this->setter[$className] = []; - } - $this->setter[$className][$name] = $method; - } - - - /** - * @param string $className - * @param string $name - * @return bool - */ - public function has(string $className, string $name): bool - { - return isset($this->setter[$className]) && isset($this->setter[$className][$name]); - } - - - /** - * @param string $className - * @return array|null - */ - public function getAll(string $className): ?array - { - return $this->setter[$className] ?? null; - } - - - /** - * @param ModelInterface $class - * @param string $key - * @param mixed $value - * @return mixed - */ - public function override(ModelInterface $class, string $key, mixed $value): mixed - { - $method = $this->setter[$class::class][$key] ?? null; - if ($method !== null) { - return $class->{$method}($value); - } - return $value; - } - - - - /** - * @param string $className - * @param string $name - * @return string|null - */ - public function get(string $className, string $name): ?string - { - if (!$this->has($className, $name)) { - return null; - } - return $this->setter[$className][$name]; - } - - -} diff --git a/Collection.php b/Collection.php index f4a7fed..91bec19 100644 --- a/Collection.php +++ b/Collection.php @@ -59,16 +59,14 @@ class Collection extends AbstractCollection public function update(array $attributes): bool { $lists = []; - $primary = $this->getModel()->getPrimary(); - $items = $this->getItems(); - if ($this->isEmpty() || !isset($items[0][$primary])) { - return false; - } - foreach ($items as $item) { - $lists[] = $item[$primary]; - } - return $this->getModel()::query()->whereIn($primary, $lists) - ->update($attributes); + $model = $this->getModel(); + if (!$this->isEmpty()) { + foreach ($this->_item as $item) { + $lists[] = $item[$model->getPrimary()]; + } + return $model::query()->whereIn($model->getPrimary(), $lists)->update($attributes); + } + return false; } /** @@ -185,8 +183,7 @@ class Collection extends AbstractCollection { $model = $this->getModel(); if ($model->hasPrimary()) { - $key = $model->getPrimary(); - return $model::query()->whereIn($key, $this->column($key))->delete(); + return $model::query()->whereIn($model->getPrimary(), $this->column($model->getPrimary()))->delete(); } throw new Exception('Must set primary key. if you wante delete'); } diff --git a/Command.php b/Command.php index eae8ca1..8f7c4a9 100644 --- a/Command.php +++ b/Command.php @@ -15,6 +15,7 @@ use Kiri\Abstracts\Component; use Kiri\Di\Container; use Kiri\Exception\ConfigException; use PDO; +use PDOStatement; use ReflectionException; use Throwable; @@ -77,12 +78,7 @@ class Command extends Component public function all(): bool|array { try { - $client = $this->connection->getConnection(); - if (($prepare = $client->prepare($this->sql)) === false) { - throw new Exception($client->errorInfo()[1]); - } - $prepare->execute($this->params); - return $prepare->fetchAll(PDO::FETCH_ASSOC); + return $this->prepare()->fetchAll(PDO::FETCH_ASSOC); } catch (Throwable $throwable) { if ($this->canReconnect($throwable->getMessage())) { return $this->all(); @@ -100,12 +96,7 @@ class Command extends Component public function one(): null|bool|array { try { - $client = $this->connection->getConnection(); - if (($prepare = $client->prepare($this->sql)) === false) { - throw new Exception($client->errorInfo()[1]); - } - $prepare->execute($this->params); - return $prepare->fetch(PDO::FETCH_ASSOC); + return $this->prepare()->fetch(PDO::FETCH_ASSOC); } catch (Throwable $throwable) { if ($this->canReconnect($throwable->getMessage())) { return $this->one(); @@ -123,12 +114,7 @@ class Command extends Component public function fetchColumn(): null|bool|array { try { - $client = $this->connection->getConnection(); - if (($prepare = $client->prepare($this->sql)) === false) { - throw new Exception($client->errorInfo()[1]); - } - $prepare->execute($this->params); - return $prepare->fetchColumn(PDO::FETCH_ASSOC); + return $this->prepare()->fetchColumn(PDO::FETCH_ASSOC); } catch (Throwable $throwable) { if ($this->canReconnect($throwable->getMessage())) { return $this->fetchColumn(); @@ -146,12 +132,7 @@ class Command extends Component public function rowCount(): int|bool { try { - $client = $this->connection->getConnection(); - if (($prepare = $client->prepare($this->sql)) === false) { - throw new Exception($client->errorInfo()[1]); - } - $prepare->execute($this->params); - return $prepare->rowCount(); + return $this->prepare()->rowCount(); } catch (Throwable $throwable) { if ($this->canReconnect($throwable->getMessage())) { return $this->rowCount(); @@ -163,6 +144,21 @@ class Command extends Component } + /** + * @return PDOStatement + * @throws Exception + */ + protected function prepare(): PDOStatement + { + $client = $this->connection->getConnection(); + if (($prepare = $client->prepare($this->sql)) === false) { + throw new Exception($client->errorInfo()[1]); + } + $prepare->execute($this->params); + return $prepare; + } + + /** * @return int|bool * @throws Exception @@ -173,7 +169,6 @@ class Command extends Component } - /** * @return bool|int * @throws ConfigException @@ -230,8 +225,7 @@ class Command extends Component */ private function error(Throwable $throwable): bool { - $message = $this->sql . '.' . json_encode($this->params, JSON_UNESCAPED_UNICODE) . PHP_EOL . jTraceEx($throwable); - return addError($message, 'mysql'); + return trigger_print_error($this->sql . '.' . json_encode($this->params, JSON_UNESCAPED_UNICODE) . PHP_EOL . jTraceEx($throwable), 'mysql'); } diff --git a/Db.php b/Db.php index a508f29..4084817 100644 --- a/Db.php +++ b/Db.php @@ -19,6 +19,7 @@ use Kiri; use Kiri\Exception\ConfigException; use Psr\Container\ContainerExceptionInterface; use Psr\Container\NotFoundExceptionInterface; +use ReflectionException; use Throwable; /** @@ -56,7 +57,9 @@ class Db implements ISqlBuilder /** * @return void - * @throws Exception + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + * @throws ReflectionException */ public static function beginTransaction(): void { @@ -78,8 +81,7 @@ class Db implements ISqlBuilder try { $result = call_user_func($closure, ...$params); } catch (Throwable $throwable) { - error($throwable); - $result = addError($throwable->getMessage(), 'mysql'); + $result = trigger_print_error($throwable->getMessage(), 'mysql'); } finally { if ($result === false) { static::rollback(); @@ -93,6 +95,9 @@ class Db implements ISqlBuilder /** * @return void + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + * @throws ReflectionException */ public static function commit(): void { @@ -102,6 +107,9 @@ class Db implements ISqlBuilder /** * @return void + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + * @throws ReflectionException */ public static function rollback(): void { diff --git a/Model.php b/Model.php index a1f173b..4ea6664 100644 --- a/Model.php +++ b/Model.php @@ -10,15 +10,10 @@ declare(strict_types=1); namespace Database; -use Database\Base\Getter; -use Database\Traits\HasBase; use Exception; use Kiri; -use Kiri\Exception\NotFindClassException; -use Kiri\Error\StdoutLoggerInterface; use Psr\Container\ContainerExceptionInterface; use Psr\Container\NotFoundExceptionInterface; -use ReflectionException; defined('SAVE_FAIL') or define('SAVE_FAIL', 3227); defined('FIND_OR_CREATE_MESSAGE') or define('FIND_OR_CREATE_MESSAGE', 'Create a new model, but the data cannot be empty.'); @@ -185,7 +180,7 @@ class Model extends Base\Model public static function inserts(array $data): bool { if (empty($data)) { - return addError('Insert data empty.', 'mysql'); + return trigger_print_error('Insert data empty.', 'mysql'); } return static::query()->insert($data); } @@ -196,15 +191,15 @@ class Model extends Base\Model */ public function delete(): bool { - if (!$this->beforeDelete()) { - return false; + if ($this->beforeDelete()) { + if ($this->hasPrimary()) { + $result = static::deleteByCondition("id = :id", [":id" => $this->getPrimaryValue()]); + } else { + $result = static::deleteByCondition($this->_attributes); + } + return $this->afterDelete($result); } - if ($this->hasPrimary()) { - $result = static::deleteByCondition("id = :id", [":id" => $this->getPrimaryValue()]); - } else { - $result = static::deleteByCondition($this->_attributes); - } - return $this->afterDelete($result); + return false; } @@ -217,8 +212,7 @@ class Model extends Base\Model */ public static function updateAll(mixed $condition, array $attributes = []): bool { - $condition = static::query()->where($condition); - return $condition->update($attributes); + return static::query()->where($condition)->update($attributes); } diff --git a/Mysql/Columns.php b/Mysql/Columns.php index bdf2e78..9e26c21 100644 --- a/Mysql/Columns.php +++ b/Mysql/Columns.php @@ -25,382 +25,385 @@ use Kiri\Core\Json; class Columns extends Component { - /** - * @var array - * field types - */ - private array $columns = []; + /** + * @var array + * field types + */ + private array $columns = []; - /** - * @var Connection - * Mysql client - */ - public Connection $db; + /** + * @var string + * tableName + */ + public string $table = ''; - /** - * @var string - * tableName - */ - public string $table = ''; + /** + * @var array + * field primary key + */ + private array $_primary = []; - /** - * @var array - * field primary key - */ - private array $_primary = []; - - /** - * @var array - * by mysql field auto_increment - */ - private array $_auto_increment = []; + /** + * @var array + * by mysql field auto_increment + */ + private array $_auto_increment = []; - private array $_fields = []; - - /** - * @param string $table - * @return $this - * @throws Exception - */ - public function table(string $table): static - { - $this->structure($this->table = $table); - return $this; - } - - /** - * @return string - */ - public function getTable(): string - { - return $this->table; - } - - /** - * @param $key - * @param $val - * @return mixed - * @throws Exception - */ - public function fieldFormat($key, $val): mixed - { - return $this->encode($val, $this->get_fields($key)); - } - - /** - * @param $data - * @return array - * @throws - */ - public function populate($data): array - { - $column = $this->get_fields(); - foreach ($data as $key => $val) { - if (!isset($column[$key])) { - continue; - } - $data[$key] = $this->decode($val, $column[$key]); - } - return $data; - } - - /** - * @param $val - * @param null $format - * @return mixed - */ - public function decode($val, $format = null): mixed - { - if (empty($format) || $val === null) { - return $val; - } - $format = strtolower($format); - if ($this->isInt($format)) { - return (int)$val; - } else if ($this->isJson($format)) { - return Json::decode($val, true); - } else if ($this->isFloat($format)) { - return (float)$val; - } else { - return stripslashes((string)$val); - } - } + private array $_fields = []; - /** - * @param string $name - * @param $value - * @return mixed - * @throws Exception - */ - public function _decode(string $name, $value): mixed - { - return $this->decode($value, $this->get_fields($name)); - } + /** + * @param Connection $db + */ + public function __construct(public Connection $db) + { + parent::__construct(); + } + + /** + * @param string $table + * @return $this + * @throws Exception + */ + public function table(string $table): static + { + $this->structure($this->table = $table); + return $this; + } + + /** + * @return string + */ + public function getTable(): string + { + return $this->table; + } + + /** + * @param $key + * @param $val + * @return string|int|bool|float + * @throws Exception + */ + public function fieldFormat($key, $val): string|int|bool|float + { + return $this->encode($val, $this->get_fields($key)); + } + + /** + * @param $data + * @return array + * @throws + */ + public function populate($data): array + { + $column = $this->get_fields(); + foreach ($data as $key => $val) { + if (!isset($column[$key])) { + continue; + } + $data[$key] = $this->decode($val, $column[$key]); + } + return $data; + } + + /** + * @param $val + * @param null $format + * @return mixed + */ + public function decode($val, $format = null): mixed + { + if (empty($format) || $val === null) { + return $val; + } + $format = strtolower($format); + if ($this->isInt($format)) { + return (int)$val; + } else if ($this->isJson($format)) { + return Json::decode($val, true); + } else if ($this->isFloat($format)) { + return (float)$val; + } else { + return stripslashes((string)$val); + } + } - /** - * @param $val - * @param null $format - * @return float|bool|int|string - * @throws Exception - */ - public function encode($val, $format = null): float|bool|int|string - { - if (empty($format)) { - return $val; - } - $format = strtolower($format); - if ($this->isInt($format)) { - return (int)$val; - } else if ($this->isJson($format)) { - return Json::encode($val); - } else if ($this->isFloat($format)) { - return (float)$val; - } else { - return addslashes($val); - } - } - - /** - * @param $format - * @return bool - */ - #[Pure] public function isInt($format): bool - { - return in_array($format, ['int', 'bigint', 'tinyint', 'smallint', 'mediumint']); - } - - /** - * @param $format - * @return bool - */ - #[Pure] public function isFloat($format): bool - { - return in_array($format, ['float', 'double', 'decimal']); - } - - /** - * @param $format - * @return bool - */ - #[Pure] public function isJson($format): bool - { - return $format == 'json'; - } - - /** - * @param $format - * @return bool - */ - #[Pure] public function isString($format): bool - { - return in_array($format, ['varchar', 'char', 'text', 'longtext', 'tinytext', 'mediumtext']); - } + /** + * @param string $name + * @param $value + * @return mixed + * @throws Exception + */ + public function _decode(string $name, $value): mixed + { + return $this->decode($value, $this->get_fields($name)); + } - /** - * @return array - * @throws - */ - public function format(): array - { - return $this->columns('Default', 'Field'); - } + /** + * @param $val + * @param null $format + * @return float|bool|int|string + * @throws Exception + */ + public function encode($val, $format = null): float|bool|int|string + { + if (empty($format)) { + return $val; + } + $format = strtolower($format); + if ($this->isInt($format)) { + return (int)$val; + } else if ($this->isJson($format)) { + return Json::encode($val); + } else if ($this->isFloat($format)) { + return (float)$val; + } else { + return addslashes($val); + } + } + + /** + * @param $format + * @return bool + */ + #[Pure] public function isInt($format): bool + { + return in_array($format, ['int', 'bigint', 'tinyint', 'smallint', 'mediumint']); + } + + /** + * @param $format + * @return bool + */ + #[Pure] public function isFloat($format): bool + { + return in_array($format, ['float', 'double', 'decimal']); + } + + /** + * @param $format + * @return bool + */ + #[Pure] public function isJson($format): bool + { + return $format == 'json'; + } + + /** + * @param $format + * @return bool + */ + #[Pure] public function isString($format): bool + { + return in_array($format, ['varchar', 'char', 'text', 'longtext', 'tinytext', 'mediumtext']); + } - /** - * @return mixed - * @throws Exception - */ - public function getFields(): array - { - if (empty($this->_fields)) { - $this->structure($this->table); - } - return $this->_fields[$this->table]; - } + /** + * @return array + * @throws + */ + public function format(): array + { + return $this->columns('Default', 'Field'); + } - /** - * @param string $name - * @return bool - * @throws Exception - */ - public function hasField(string $name): bool - { - return array_key_exists($name, $this->getFields()); - } + /** + * @return mixed + * @throws Exception + */ + public function getFields(): array + { + if (empty($this->_fields)) { + $this->structure($this->table); + } + return $this->_fields[$this->table]; + } - /** - * @return int|string|null - * @throws Exception - */ - public function getAutoIncrement(): int|string|null - { - return $this->_auto_increment[$this->table] ?? null; - } - - /** - * @return array|null|string - * - * @throws Exception - */ - public function getPrimaryKeys(): array|string|null - { - if (isset($this->_auto_increment[$this->table])) { - return $this->_auto_increment[$this->table]; - } - return $this->_primary[$this->table] ?? null; - } - - /** - * @return array|null|string - * - * @throws Exception - */ - #[Pure] public function getFirstPrimary(): array|string|null - { - if (isset($this->_auto_increment[$this->table])) { - return $this->_auto_increment[$this->table]; - } - if (isset($this->_primary[$this->table])) { - return current($this->_primary[$this->table]); - } - return null; - } - - /** - * @param $name - * @param null $index - * @return array - * @throws Exception - */ - private function columns($name, $index = null): array - { - if (empty($index)) { - return array_column($this->getColumns(), $name); - } else { - return array_column($this->getColumns(), $name, $index); - } - } - - /** - * @return array|static - * @throws Exception - */ - private function getColumns(): array|static - { - return $this->structure($this->getTable()); - } + /** + * @param string $name + * @return bool + * @throws Exception + */ + public function hasField(string $name): bool + { + return array_key_exists($name, $this->getFields()); + } - /** - * @param $table - * @return array|Columns - * @throws Exception - */ - private function structure($table): array|static - { - if (!isset($this->columns[$table]) || empty($this->columns[$table])) { - $column = $this->db->createCommand(SqlBuilder::builder(null)->columns($table))->all(); - if (empty($column)) { - throw new Exception("The table " . $table . " not exists."); - } - return $this->columns[$table] = $this->resolve($column, $table); - } - return $this->columns[$table]; - } + /** + * @return int|string|null + * @throws Exception + */ + public function getAutoIncrement(): int|string|null + { + return $this->_auto_increment[$this->table] ?? null; + } + + /** + * @return array|null|string + * + * @throws Exception + */ + public function getPrimaryKeys(): array|string|null + { + if (isset($this->_auto_increment[$this->table])) { + return $this->_auto_increment[$this->table]; + } + return $this->_primary[$this->table] ?? null; + } + + /** + * @return array|null|string + * + * @throws Exception + */ + #[Pure] public function getFirstPrimary(): array|string|null + { + if (isset($this->_auto_increment[$this->table])) { + return $this->_auto_increment[$this->table]; + } + if (isset($this->_primary[$this->table])) { + return current($this->_primary[$this->table]); + } + return null; + } + + /** + * @param $name + * @param null $index + * @return array + * @throws Exception + */ + private function columns($name, $index = null): array + { + if (empty($index)) { + return array_column($this->getColumns(), $name); + } else { + return array_column($this->getColumns(), $name, $index); + } + } + + /** + * @return array|static + * @throws Exception + */ + private function getColumns(): array|static + { + return $this->structure($this->getTable()); + } - /** - * @param array $column - * @param $table - * @return array - */ - private function resolve(array $column, $table): array - { - foreach ($column as $key => $item) { - $this->addPrimary($item, $table); - $column[$key]['Type'] = $this->clean($item['Type']); - } - - $this->_fields[$table] = array_column($column, 'Default', 'Field'); - - return $column; - } - - /** - * @param $item - * @param $table - */ - private function addPrimary($item, $table) - { - if (!isset($this->_primary[$table])) { - $this->_primary[$table] = []; - } - if ($item['Key'] === 'PRI') { - $this->_primary[$table][] = $item['Field']; - } - $this->addIncrement($item, $table); - } + /** + * @param $table + * @return array|Columns + * @throws Exception + */ + private function structure($table): array|static + { + if (!isset($this->columns[$table]) || empty($this->columns[$table])) { + $column = $this->db->createCommand(SqlBuilder::builder(null)->columns($table))->all(); + if (empty($column)) { + throw new Exception("The table " . $table . " not exists."); + } + return $this->columns[$table] = $this->resolve($column, $table); + } + return $this->columns[$table]; + } - /** - * @param $item - * @param $table - */ - private function addIncrement($item, $table) - { - if ($item['Extra'] !== 'auto_increment') { - return; - } - $this->_auto_increment[$table] = $item['Field']; - } + /** + * @param array $column + * @param $table + * @return array + */ + private function resolve(array $column, $table): array + { + foreach ($column as $key => $item) { + $this->addPrimary($item, $table); + $column[$key]['Type'] = $this->clean($item['Type']); + } + + $this->_fields[$table] = array_column($column, 'Default', 'Field'); + + return $column; + } + + /** + * @param $item + * @param $table + */ + private function addPrimary($item, $table) + { + if (!isset($this->_primary[$table])) { + $this->_primary[$table] = []; + } + if ($item['Key'] === 'PRI') { + $this->_primary[$table][] = $item['Field']; + } + $this->addIncrement($item, $table); + } - /** - * @param $type - * @return string - */ - public function clean($type): string - { - if (!str_contains($type, ')')) { - return $type; - } - $replace = preg_replace('/\(\d+(,\d+)?\)(\s+\w+)*/', '', $type); - if (str_contains($replace, ' ')) { - $replace = explode(' ', $replace)[1]; - } - return $replace; - } + /** + * @param $item + * @param $table + */ + private function addIncrement($item, $table) + { + if ($item['Extra'] !== 'auto_increment') { + return; + } + $this->_auto_increment[$table] = $item['Field']; + } - /** - * @param null $field - * @return array|string|null - * @throws Exception - */ - public function get_fields($field = null): array|string|null - { - $fields = $this->getAllField(); - if (empty($field)) { - return $fields; - } - if (isset($fields[$field])) { - return strtolower($fields[$field]); - } - return null; - } - /** - * @return array - * @throws Exception - */ - public function getAllField(): array - { - return $this->columns('Type', 'Field'); - } + /** + * @param $type + * @return string + */ + public function clean($type): string + { + if (!str_contains($type, ')')) { + return $type; + } + $replace = preg_replace('/\(\d+(,\d+)?\)(\s+\w+)*/', '', $type); + if (str_contains($replace, ' ')) { + $replace = explode(' ', $replace)[1]; + } + return $replace; + } + + /** + * @param null $field + * @return array|string|null + * @throws Exception + */ + public function get_fields($field = null): array|string|null + { + $fields = $this->getAllField(); + if (empty($field)) { + return $fields; + } + if (isset($fields[$field])) { + return strtolower($fields[$field]); + } + return null; + } + + /** + * @return array + * @throws Exception + */ + public function getAllField(): array + { + return $this->columns('Type', 'Field'); + } } diff --git a/Mysql/Schema.php b/Mysql/Schema.php index 9f5ea4e..58559c4 100644 --- a/Mysql/Schema.php +++ b/Mysql/Schema.php @@ -28,7 +28,7 @@ class Schema extends Component public function getColumns(): ?Columns { if ($this->_column === null) { - $this->_column = new Columns(['db' => $this->db]); + $this->_column = new Columns($this->db); } return $this->_column; diff --git a/Pagination.php b/Pagination.php index 5cf9a22..1df720a 100644 --- a/Pagination.php +++ b/Pagination.php @@ -15,193 +15,197 @@ use Kiri\Abstracts\Component; class Pagination extends Component { - /** @var ActiveQuery */ - private ActiveQuery $activeQuery; + /** @var ActiveQuery */ + private ActiveQuery $activeQuery; - /** @var int 从第几个开始查 */ - private int $_offset = 0; + /** @var int 从第几个开始查 */ + private int $_offset = 0; - /** @var int 每页数量 */ - private int $_limit = 100; + /** @var int 每页数量 */ + private int $_limit = 100; - /** @var int 最大查询数量 */ - private int $_max = 0; + /** @var int 最大查询数量 */ + private int $_max = 0; - /** @var int 当前已查询数量 */ - private int $_length = 0; + /** @var int 当前已查询数量 */ + private int $_length = 0; - /** @var Closure */ - private Closure $_callback; + /** @var Closure */ + private Closure $_callback; - /** - * PaginationIteration constructor. - * @param ActiveQuery $activeQuery - * @param array $config - * @throws Exception - */ - public function __construct(ActiveQuery $activeQuery, array $config = []) - { - parent::__construct(); - $this->activeQuery = $activeQuery; - } + /** + * PaginationIteration constructor. + * @param ActiveQuery $activeQuery + * @param array $config + * @throws Exception + */ + public function __construct(ActiveQuery $activeQuery, array $config = []) + { + parent::__construct(); + $this->activeQuery = $activeQuery; + } - public function clean() - { - unset($this->activeQuery, $this->_callback, $this->_group); - $this->_offset = 0; - $this->_limit = 100; - $this->_max = 0; - $this->_length = 0;; - } + /** + * @return void + */ + public function clean(): void + { + unset($this->activeQuery, $this->_callback, $this->_group); + $this->_offset = 0; + $this->_limit = 100; + $this->_max = 0; + $this->_length = 0;; + } - /** - * recover class by clone - */ - public function __clone() - { - $this->clean(); - } + /** + * recover class by clone + */ + public function __clone() + { + $this->clean(); + } - /** - * @param array|Closure $callback - * @throws Exception - */ - public function setCallback(array|Closure $callback) - { - if (!is_callable($callback, true)) { - throw new Exception('非法回调函数~'); - } - $this->_callback = $callback; - } + /** + * @param array|Closure $callback + * @throws Exception + */ + public function setCallback(array|Closure $callback) + { + if (!is_callable($callback, true)) { + throw new Exception('非法回调函数~'); + } + $this->_callback = $callback; + } - /** - * @param int $number - * @return Pagination - */ - public function setOffset(int $number): static - { - if ($number < 0) { - $number = 0; - } - $this->_offset = $number; - return $this; - } + /** + * @param int $number + * @return Pagination + */ + public function setOffset(int $number): static + { + if ($number < 0) { + $number = 0; + } + $this->_offset = $number; + return $this; + } - /** - * @param int $number - * @return Pagination - */ - public function setLimit(int $number): static - { - if ($number < 1) { - $number = 100; - } else if ($number > 5000) { - $number = 5000; - } - $this->_limit = $number; - return $this; - } + /** + * @param int $number + * @return Pagination + */ + public function setLimit(int $number): static + { + if ($number < 1) { + $number = 100; + } else if ($number > 5000) { + $number = 5000; + } + $this->_limit = $number; + return $this; + } - /** - * @param int $number - * @return Pagination - */ - public function setMax(int $number): static - { - if ($number < 0) { - return $this; - } - $this->_max = $number; - return $this; - } + /** + * @param int $number + * @return Pagination + */ + public function setMax(int $number): static + { + if ($number < 0) { + return $this; + } + $this->_max = $number; + return $this; + } - /** - * @param array $param - * @return void - * @throws Exception - */ - public function plunk(array $param = []): void - { - $this->loop($param); - } + /** + * @param array $param + * @return void + * @throws Exception + */ + public function plunk(array $param = []): void + { + $this->loop($param); + } - /** - * 轮训 - * @param $param - * @return array - * @throws Exception - */ - public function loop($param): array - { - if ($this->_max > 0 && $this->_length >= $this->_max) { - return $this->output(); - } - [$length, $data] = $this->get(); - try { - call_user_func($this->_callback, $data, $param); - } catch (\Throwable $exception) { - error($exception); - } finally { - $data = null; - } - if ($length < $this->_limit) { - return $this->output(); - } - return $this->loop($param); - } + /** + * 轮训 + * @param $param + * @return array + * @throws Exception + */ + public function loop($param): array + { + if ($this->_max > 0 && $this->_length >= $this->_max) { + return $this->output(); + } + [$length, $data] = $this->get(); + try { + call_user_func($this->_callback, $data, $param); + } catch (\Throwable $exception) { + error($exception); + } finally { + $data = null; + } + if ($length < $this->_limit) { + return $this->output(); + } + return $this->loop($param); + } - /** - * @return array - */ - public function output(): array - { - return []; - } + /** + * @return array + */ + public function output(): array + { + return []; + } - /** - * @param $data - * @param $param - * @throws Exception - */ - private function executed($data, $param): void - { - try { - call_user_func($this->_callback, $data, $param); - } catch (\Throwable $exception) { - error($exception); - } - } + /** + * @param $data + * @param $param + * @throws Exception + */ + private function executed($data, $param): void + { + try { + call_user_func($this->_callback, $data, $param); + } catch (\Throwable $exception) { + error($exception); + } + } - /** - * @return array|Collection - */ - private function get(): Collection|array - { - if ($this->_max > 0 && $this->_length + $this->_limit > $this->_max) { - $this->_limit = $this->_length + $this->_limit - $this->_max; - } - $data = $this->activeQuery->offset($this->_offset)->limit($this->_limit)->get(); - $this->_offset += $this->_limit; + /** + * @return array|Collection + * @throws Exception + */ + private function get(): Collection|array + { + if ($this->_max > 0 && $this->_length + $this->_limit > $this->_max) { + $this->_limit = $this->_length + $this->_limit - $this->_max; + } + $data = $this->activeQuery->offset($this->_offset)->limit($this->_limit)->get(); + $this->_offset += $this->_limit; - if (is_array($data)) { - $size = count($data); - } else { - $size = $data->size(); - } - $this->_length += $size; - return [$size, $data]; - } + if (is_array($data)) { + $size = count($data); + } else { + $size = $data->size(); + } + $this->_length += $size; + return [$size, $data]; + } } diff --git a/SqlBuilder.php b/SqlBuilder.php index 7b8454f..fd911ac 100644 --- a/SqlBuilder.php +++ b/SqlBuilder.php @@ -105,9 +105,8 @@ class SqlBuilder extends Component private function __updateBuilder(array $string): string|bool { if (empty($string)) { - return \Kiri::getLogger()->addError('None data update.'); + return \Kiri::getLogger()->failure('None data update.'); } - return 'UPDATE ' . $this->query->from . ' SET ' . implode(',', $string) . $this->_prefix(); } diff --git a/Traits/Builder.php b/Traits/Builder.php index c7ff359..b38b62d 100644 --- a/Traits/Builder.php +++ b/Traits/Builder.php @@ -112,23 +112,13 @@ trait Builder /** * @param array $where * @return string - * @throws NotFindClassException - * @throws ReflectionException - */ + */ private function where(array $where): string { if (count($where) < 1) { return ''; } - $_tmp = []; - foreach ($where as $key => $value) { - $_tmp[] = $this->resolveCondition($key, $value, $_tmp); - } - if (count($_tmp) > 0) { - return implode(' AND ', $_tmp); - } else { - return ''; - } + return implode(' AND ', $where); } diff --git a/Traits/QueryTrait.php b/Traits/QueryTrait.php index beb1b03..a764ce8 100644 --- a/Traits/QueryTrait.php +++ b/Traits/QueryTrait.php @@ -12,14 +12,11 @@ namespace Database\Traits; use Closure; use Database\ActiveQuery; -use Database\Condition\MathematicsCondition; use Database\ModelInterface; use Database\Query; use Database\SqlBuilder; use Exception; -use Kiri\Exception\NotFindClassException; use Kiri; -use ReflectionException; /** * Trait QueryTrait @@ -27,874 +24,766 @@ use ReflectionException; */ trait QueryTrait { - public array $where = []; - public array $select = []; - public array $join = []; - public array $order = []; - public int $offset = 0; - public int $limit = 0; - public string $group = ''; - public string $from = ''; - public string $alias = 't1'; - public array $filter = []; - - - public bool $lock = false; - - public bool $ifNotWhere = false; - - - private SqlBuilder $builder; - - /** - * @var ModelInterface|string|null - */ - public ModelInterface|string|null $modelClass; - - /** - * clear - */ - public function clear(): void - { - $this->where = []; - $this->select = []; - $this->join = []; - $this->order = []; - $this->offset = 0; - $this->limit = 500; - $this->group = ''; - $this->from = ''; - $this->alias = 't1'; - $this->filter = []; - } - - - /** - * @param string $column - * @param callable $callable - * @return $this - */ - public function when(string $column, callable $callable): static - { - $caseWhen = new When($column, $this); - - call_user_func($callable, $caseWhen); - - $this->where[] = $caseWhen->end(); - - return $this; - } - - - /** - * @param bool $lock - * @return $this - */ - public function lock(bool $lock): static - { - $this->lock = $lock; - return $this; - } - - - /** - * @param string $whereRaw - * @return QueryTrait - */ - public function whereRaw(string $whereRaw): static - { - if ($whereRaw == '') { - return $this; - } - $this->where[] = $whereRaw; - return $this; - } - - - /** - * @param bool $bool - * @return $this - */ - public function ifNotWhere(bool $bool): static - { - $this->ifNotWhere = $bool; - return $this; - } - - /** - * @return string - * @throws - */ - public function getTable(): string - { - return $this->modelClass->getTable(); - } - - - /** - * @param string $column - * @param string $value - * @return $this - */ - public function whereLocate(string $column, string $value): static - { - $this->where[] = 'LOCATE(' . $column . ',\'' . addslashes($value) . '\') > 0'; - return $this; - } - - - /** - * @param string $column - * @return $this - */ - public function whereNull(string $column): static - { - $this->where[] = $column . ' IS NULL'; - return $this; - } - - - /** - * @param string $column - * @return $this - */ - public function whereEmpty(string $column): static - { - $this->where[] = $column . ' = \'\''; - return $this; - } - - /** - * @param string $column - * @return $this - */ - public function whereNotEmpty(string $column): static - { - $this->where[] = $column . ' <> \'\''; - return $this; - } - - /** - * @param string $column - * @return $this - */ - public function whereNotNull(string $column): static - { - $this->where[] = $column . ' IS NOT NULL'; - return $this; - } - - - /** - * @param string $alias - * - * @return $this - * - * select * from tableName as t1 - */ - public function alias(string $alias = 't1'): static - { - $this->alias = $alias; - return $this; - } - - /** - * @param string|Closure $tableName - * - * @return $this - */ - public function from(string|Closure $tableName): static - { - if ($tableName instanceof Closure) { - $tableName = call_user_func($tableName, $this->makeNewSqlGenerate()); - } - $this->from = $tableName; - return $this; - } - - /** - * @param string $tableName - * @param string $alias - * @param null $on - * @param array|null $param - * @return $this - * $query->join([$tableName, ['userId'=>'uuvOd']], $param) - * $query->join([$tableName, ['userId'=>'uuvOd'], $param]) - * $query->join($tableName, ['userId'=>'uuvOd',$param]) - */ - private function join(string $tableName, string $alias, $on = NULL, array $param = NULL): static - { - if (empty($on)) { - return $this; - } - $join[] = $tableName . ' AS ' . $alias; - $join[] = 'ON ' . $this->onCondition($alias, $on); - if (empty($join)) { - return $this; - } - - $this->join[] = implode(' ', $join); - if (!empty($param)) { - $this->addParams($param); - } - - return $this; - } - - /** - * @param $alias - * @param $on - * @return string - */ - private function onCondition($alias, $on): string - { - $array = []; - foreach ($on as $key => $item) { - if (!str_contains($item, '.')) { - $this->addParam($key, $item); - } else { - $explode = explode('.', $item); - if (isset($explode[1]) && ($explode[0] == $alias || $this->alias == $explode[0])) { - $array[] = $key . '=' . $item; - } else { - $this->addParam($key, $item); - } - } - } - return implode(' AND ', $array); - } - - /** - * @param string $tableName - * @param string $alias - * @param $onCondition - * @param null $param - * @return $this - * @throws - */ - public function leftJoin(string $tableName, string $alias, $onCondition, $param = NULL): static - { - if (class_exists($tableName)) { - $model = Kiri::getDi()->get($tableName); - if (!($model instanceof ModelInterface)) { - throw new Exception('Model must implement ' . ModelInterface::class); - } - $tableName = $model->getTable(); - } - return $this->join("LEFT JOIN " . $tableName, $alias, $onCondition, $param); - } - - /** - * @param $tableName - * @param $alias - * @param $onCondition - * @param null $param - * @return $this - * @throws - */ - public function rightJoin($tableName, $alias, $onCondition, $param = NULL): static - { - if (class_exists($tableName)) { - $model = Kiri::getDi()->get($tableName); - if (!($model instanceof ModelInterface)) { - throw new Exception('Model must implement ' . ModelInterface::class); - } - $tableName = $model->getTable(); - } - return $this->join("RIGHT JOIN " . $tableName, $alias, $onCondition, $param); - } - - /** - * @param $tableName - * @param $alias - * @param $onCondition - * @param null $param - * @return $this - * @throws - */ - public function innerJoin($tableName, $alias, $onCondition, $param = NULL): static - { - if (class_exists($tableName)) { - $model = Kiri::getDi()->get($tableName); - if (!($model instanceof ModelInterface)) { - throw new Exception('Model must implement ' . ModelInterface::class); - } - $tableName = $model->getTable(); - } - return $this->join("INNER JOIN " . $tableName, $alias, $onCondition, $param); - } - - /** - * @param $array - * - * @return string - */ - private function toString($array): string - { - $tmp = []; - if (!is_array($array)) { - return $array; - } - foreach ($array as $key => $val) { - if (is_array($val)) { - $tmp[] = $this->toString($array); - } else { - $tmp[] = $key . '=:' . $key; - $this->attributes[':' . $key] = $val; - } - } - return implode(' AND ', $tmp); - } - - /** - * @param string $field - * - * @return $this - */ - public function sum(string $field): static - { - $this->select[] = 'SUM(' . $field . ') AS ' . $field; - return $this; - } - - /** - * @param string $field - * @return $this - */ - public function max(string $field): static - { - $this->select[] = 'MAX(' . $field . ') AS ' . $field; - return $this; - } - - /** - * @param string $lngField - * @param string $latField - * @param int $lng1 - * @param int $lat1 - * - * @return $this - */ - public function distance(string $lngField, string $latField, int $lng1, int $lat1): static - { - $sql = "ROUND(6378.138 * 2 * ASIN(SQRT(POW(SIN(($lat1 * PI() / 180 - $lat1 * PI() / 180) / 2),2) + COS($lat1 * PI() / 180) * COS($latField * PI() / 180) * POW(SIN(($lng1 * PI() / 180 - $lngField * PI() / 180) / 2),2))) * 1000) AS distance"; - $this->select[] = $sql; - return $this; - } - - /** - * @param string|array $column - * @param string $sort - * - * @return $this - * - * [ - * 'addTime', - * 'descTime desc' - * ] - */ - public function orderBy(string|array $column, string $sort = 'DESC'): static - { - if (empty($column)) { - return $this; - } - if (is_string($column)) { - return $this->addOrder(...func_get_args()); - } - - foreach ($column as $val) { - $this->addOrder($val); - } - - return $this; - } - - /** - * @param string $column - * @param string $sort - * - * @return $this - * - */ - private function addOrder(string $column, string $sort = 'DESC'): static - { - if (func_num_args() == 1 || str_contains($column, ' ')) { - $this->order[] = $column; - } else { - $this->order[] = "$column $sort"; - } - return $this; - } - - /** - * @param array|string $column - * - * @return $this - */ - public function select(array|string $column = '*'): static - { - if ($column == '*') { - $this->select = [$column]; - } else { - if (!is_array($column)) { - $column = explode(',', $column); - } - foreach ($column as $val) { - $this->select[] = $val; - } - } - return $this; - } - - /** - * @return $this - */ - public function orderRand(): static - { - $this->order[] = 'RAND()'; - return $this; - } - - /** - * @param array|Closure|string $conditionArray - * @param string $opera - * @param null $value - * @return QueryTrait - * @throws - */ - public function whereOr(array|Closure|string $conditionArray = [], string $opera = '=', $value = null): static - { - if ($conditionArray instanceof Closure) { - $conditionArray = $this->makeClosureFunction($conditionArray); - } - - if (func_num_args() > 1) { - [$conditionArray, $opera, $value] = $this->opera(...func_get_args()); - - $conditionArray = $this->sprintf($conditionArray, $value, $opera); - } - - $this->where = ['((' . implode(' AND ', $this->where) . ') OR (' . $conditionArray . '))']; - return $this; - } - - /** - * @param string $columns - * @param string|int|bool|null $value - * - * @param string $opera - * @return QueryTrait - */ - public function whereAnd(string $columns, string $opera = '=', string|int|null|bool $value = NULL): static - { - [$columns, $opera, $value] = $this->opera(...func_get_args()); - - $this->where[] = $this->sprintf($columns, $value, $opera); - return $this; - } - - - /** - * @param string $column - * @param string $value - * @return $this - */ - public function whereLike(string $column, string $value): static - { - $this->bindParam(':LIKE' . $column, $value); - $this->where[] = $column . ' LIKE \':LIKE' . $column . '\''; - return $this; - } - - /** - * @param string $column - * @param string $value - * @return $this - */ - public function whereLeftLike(string $column, string $value): static - { - $this->bindParam(':LLike' . $column, $value); - $this->where[] = $column . ' LLike \'%:LLike' . $column . '\''; - return $this; - } - - /** - * @param string $column - * @param string $value - * @return $this - */ - public function whereRightLike(string $column, string $value): static - { - $this->bindParam(':RLike' . $column, $value); - $this->where[] = $column . ' RLike \':RLike' . $column . '%\''; - return $this; - } - - - /** - * @param string $column - * @param string $value - * @return $this - */ - public function whereNotLike(string $column, string $value): static - { - $this->bindParam(':LIKE' . $column, $value); - $this->where[] = $column . ' NOT LIKE \'%:LIKE' . $column . '%\''; - return $this; - } - - /** - * @param string $column - * @param int $value - * @return $this - * @see MathematicsCondition - */ - public function whereEq(string $column, int $value): static - { - $this->bindParam(':eq' . $column, $value); - $this->where[] = $column . ' = :eq' . $column; - return $this; - } - - - /** - * @param string $column - * @param int $value - * @return $this - * @see MathematicsCondition - */ - public function whereNeq(string $column, int $value): static - { - $this->bindParam(':neq' . $column, $value); - $this->where[] = $column . ' <> :neq' . $column; - return $this; - } - - - /** - * @param string $column - * @param int $value - * @return $this - * @see MathematicsCondition - */ - public function whereGt(string $column, int $value): static - { - $this->bindParam(':gt' . $column, $value); - $this->where[] = $column . ' > :gt' . $column; - return $this; - } - - /** - * @param string $column - * @param int $value - * @return $this - * @see MathematicsCondition - */ - public function whereEgt(string $column, int $value): static - { - $this->bindParam(':egt' . $column, $value); - $this->where[] = $column . ' >= :egt' . $column; - return $this; - } - - - /** - * @param string $column - * @param int $value - * @return $this - * @see MathematicsCondition - */ - public function whereLt(string $column, int $value): static - { - $this->bindParam(':lt' . $column, $value); - $this->where[] = $column . ' < :lt' . $column; - return $this; - } - - /** - * @param string $column - * @param int $value - * @return $this - * @see MathematicsCondition - */ - public function whereElt(string $column, int $value): static - { - $this->bindParam(':elt' . $column, $value); - $this->where[] = $column . ' <= :elt' . $column; - return $this; - } - - /** - * @param string $columns - * @param array|Closure $value - * @return $this - * @throws - */ - public function whereIn(string $columns, array|Closure $value): static - { - if ($value instanceof Closure) { - $value = $this->makeClosureFunction($value); - } - if (count($value) < 1) { - $value = [-1]; - } - $this->where[] = $columns . ' IN (' . implode(',', $value) . ')'; - return $this; - } - - - /** - * @param $value - * @return ActiveQuery - * @throws - */ - public function makeNewQuery($value): ActiveQuery - { - $activeQuery = new ActiveQuery($this->modelClass); - call_user_func($value, $activeQuery); - if (empty($activeQuery->from)) { - $activeQuery->from($activeQuery->modelClass->getTable()); - } - return $activeQuery; - } - - - /** - * @return Query - * @throws - */ - public function makeNewSqlGenerate(): Query - { - return Kiri::createObject(['class' => Query::class]); - } - - - /** - * @param string $columns - * @param array $value - * @return $this - */ - public function whereNotIn(string $columns, array $value): static - { - if (count($value) < 1) { - $value = [-1]; - } - $this->where[] = $columns . ' NOT IN (' . implode(',', $value) . ')'; - return $this; - } - - /** - * @param string $column - * @param int $start - * @param int $end - * @return $this - */ - public function whereBetween(string $column, int $start, int $end): static - { - if (empty($column) || empty($start) || empty($end)) { - return $this; - } - - $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; - } - - /** - * @param string $column - * @param int $start - * @param int $end - * @return $this - */ - public function whereNotBetween(string $column, int $start, int $end): static - { - if (empty($column) || empty($start) || empty($end)) { - return $this; - } - - $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; - } - - /** - * @param array|null $params - * - * @return $this - */ - public function bindParams(?array $params = []): static - { - if ($params === null) { - return $this; - } - $this->attributes = array_merge($this->attributes, $params); - return $this; - } - - /** - * @param string $key - * @param mixed $value - * @return $this - */ - public function bindParam(string $key, mixed $value): static - { - if (is_string($value)) { - $value = addslashes($value); - } - $this->attributes[$key] = $value; - return $this; - } - - /** - * @param array|string $column - * @param string $opera - * @param null $value - * @return $this - * @throws - */ - public function where(array|string $column, string $opera = '=', $value = null): static - { - if (is_array($column)) { - return $this->addArray($column); - } - if (is_string($column)) { - $this->where[] = $column; - } else { - [$column, $opera, $value] = $this->opera(...func_get_args()); - if ($value === null) { - return $this; - } - $this->bindParam(':' . $column, $value); - $this->where[] = $column . ' ' . $opera . ':' . $column; - } - return $this; - } - - - /** - * @param Closure $closure - * @return $this - */ - public function whereClosure(Closure $closure): static - { - $this->where[] = $this->makeClosureFunction($closure); - return $this; - } - - - /** - * @param Closure|array $closure - * @return string - * @throws - */ - public function makeClosureFunction(Closure|array $closure): string - { - $generate = $this->makeNewSqlGenerate(); - if ($closure instanceof Closure) { - call_user_func($closure, $generate); - } else { - $generate->where($closure); - } - return $generate->getSql(); - } - - - /** - * @param string $name - * @param string|null $having - * - * @return $this - */ - public function groupBy(string $name, string $having = NULL): static - { - $this->group = $name; - if (empty($having)) { - return $this; - } - $this->group .= ' HAVING ' . $having; - return $this; - } - - /** - * @param int $limit - * - * @return $this - */ - public function limit(int $limit = 20): static - { - $this->limit = $limit; - return $this; - } - - - /** - * @param int $offset - * @return $this - */ - public function offset(int $offset): static - { - $this->offset = $offset; - return $this; - } - - - /** - * @return array - */ - private function opera(): array - { - if (func_num_args() == 3) { - [$column, $opera, $value] = func_get_args(); - } else { - [$column, $value] = func_get_args(); - } - if (!isset($opera)) { - $opera = '='; - } - return [$column, $opera, $value]; - } - - - /** - * @param array $array - * @return $this - */ - private function addArray(array $array): static - { - foreach ($array as $key => $value) { - if ($value === null) { - continue; - } - $this->where[] = $this->sprintf($key, $value); - } - return $this; - } - - - /** - * @param $column - * @param $value - * @param string $opera - * @return string - */ - private function sprintf($column, $value, string $opera = '='): string - { - $this->bindParam(':' . $column, $value); - return $column . ' ' . $opera . ' :' . $column; - } - - - /** - * @return $this - */ - public function oneLimit(): static - { - $this->limit = 1; - return $this; - } + public array $where = []; + public array $select = []; + public array $join = []; + public array $order = []; + public int $offset = 0; + public int $limit = 0; + public string $group = ''; + public string $from = ''; + public string $alias = 't1'; + public array $filter = []; + + + public bool $lock = false; + + public bool $ifNotWhere = false; + + + private SqlBuilder $builder; + + /** + * @var ModelInterface|string|null + */ + public ModelInterface|string|null $modelClass; + + /** + * clear + */ + public function clear(): void + { + $this->where = []; + $this->select = []; + $this->join = []; + $this->order = []; + $this->offset = 0; + $this->limit = 500; + $this->group = ''; + $this->from = ''; + $this->alias = 't1'; + $this->filter = []; + } + + + /** + * @param string $column + * @param callable $callable + * @return $this + */ + public function when(string $column, callable $callable): static + { + $caseWhen = new When($column, $this); + + call_user_func($callable, $caseWhen); + + $this->where[] = $caseWhen->end(); + + return $this; + } + + + /** + * @param bool $lock + * @return $this + */ + public function lock(bool $lock): static + { + $this->lock = $lock; + return $this; + } + + + /** + * @param string $whereRaw + * @return QueryTrait + */ + public function whereRaw(string $whereRaw): static + { + if ($whereRaw == '') { + return $this; + } + $this->where[] = $whereRaw; + return $this; + } + + /** + * @return string + * @throws + */ + public function getTable(): string + { + return $this->modelClass->getTable(); + } + + + /** + * @param string $column + * @param string $value + * @return $this + */ + public function whereLocate(string $column, string $value): static + { + $this->where[] = 'LOCATE(' . $column . ',\'' . addslashes($value) . '\') > 0'; + return $this; + } + + + /** + * @param string $column + * @return $this + */ + public function whereNull(string $column): static + { + $this->where[] = $column . ' IS NULL'; + return $this; + } + + + /** + * @param string $column + * @return $this + */ + public function whereEmpty(string $column): static + { + $this->where[] = $column . ' = \'\''; + return $this; + } + + /** + * @param string $column + * @return $this + */ + public function whereNotEmpty(string $column): static + { + $this->where[] = $column . ' <> \'\''; + return $this; + } + + /** + * @param string $column + * @return $this + */ + public function whereNotNull(string $column): static + { + $this->where[] = $column . ' IS NOT NULL'; + return $this; + } + + + /** + * @param string $alias + * + * @return $this + * + * select * from tableName as t1 + */ + public function alias(string $alias = 't1'): static + { + $this->alias = $alias; + return $this; + } + + /** + * @param string|Closure $tableName + * + * @return $this + */ + public function from(string|Closure $tableName): static + { + if ($tableName instanceof Closure) { + $tableName = call_user_func($tableName, $this->makeNewSqlGenerate()); + } + $this->from = $tableName; + return $this; + } + + /** + * @param string $tableName + * @param string $alias + * @param null $on + * @param array|null $param + * @return $this + * $query->join([$tableName, ['userId'=>'uuvOd']], $param) + * $query->join([$tableName, ['userId'=>'uuvOd'], $param]) + * $query->join($tableName, ['userId'=>'uuvOd',$param]) + */ + private function join(string $tableName, string $alias, $on = NULL, array $param = NULL): static + { + if (empty($on)) { + return $this; + } + $join[] = $tableName . ' AS ' . $alias; + $join[] = 'ON ' . $this->onCondition($alias, $on); + if (empty($join)) { + return $this; + } + + $this->join[] = implode(' ', $join); + if (!empty($param)) { + $this->addParams($param); + } + + return $this; + } + + /** + * @param $alias + * @param $on + * @return string + */ + private function onCondition($alias, $on): string + { + $array = []; + foreach ($on as $key => $item) { + if (!str_contains($item, '.')) { + $this->addParam($key, $item); + } else { + $explode = explode('.', $item); + if (isset($explode[1]) && ($explode[0] == $alias || $this->alias == $explode[0])) { + $array[] = $key . '=' . $item; + } else { + $this->addParam($key, $item); + } + } + } + return implode(' AND ', $array); + } + + /** + * @param string $tableName + * @param string $alias + * @param $onCondition + * @param null $param + * @return $this + * @throws + */ + public function leftJoin(string $tableName, string $alias, $onCondition, $param = NULL): static + { + if (class_exists($tableName)) { + $model = Kiri::getDi()->get($tableName); + if (!($model instanceof ModelInterface)) { + throw new Exception('Model must implement ' . ModelInterface::class); + } + $tableName = $model->getTable(); + } + return $this->join("LEFT JOIN " . $tableName, $alias, $onCondition, $param); + } + + /** + * @param $tableName + * @param $alias + * @param $onCondition + * @param null $param + * @return $this + * @throws + */ + public function rightJoin($tableName, $alias, $onCondition, $param = NULL): static + { + if (class_exists($tableName)) { + $model = Kiri::getDi()->get($tableName); + if (!($model instanceof ModelInterface)) { + throw new Exception('Model must implement ' . ModelInterface::class); + } + $tableName = $model->getTable(); + } + return $this->join("RIGHT JOIN " . $tableName, $alias, $onCondition, $param); + } + + /** + * @param $tableName + * @param $alias + * @param $onCondition + * @param null $param + * @return $this + * @throws + */ + public function innerJoin($tableName, $alias, $onCondition, $param = NULL): static + { + if (class_exists($tableName)) { + $model = Kiri::getDi()->get($tableName); + if (!($model instanceof ModelInterface)) { + throw new Exception('Model must implement ' . ModelInterface::class); + } + $tableName = $model->getTable(); + } + return $this->join("INNER JOIN " . $tableName, $alias, $onCondition, $param); + } + + /** + * @param $array + * + * @return string + */ + private function toString($array): string + { + $tmp = []; + if (!is_array($array)) { + return $array; + } + foreach ($array as $key => $val) { + if (is_array($val)) { + $tmp[] = $this->toString($array); + } else { + $tmp[] = $key . '=:' . $key; + $this->attributes[':' . $key] = $val; + } + } + return implode(' AND ', $tmp); + } + + /** + * @param string $field + * + * @return $this + */ + public function sum(string $field): static + { + $this->select[] = 'SUM(' . $field . ') AS ' . $field; + return $this; + } + + /** + * @param string $field + * @return $this + */ + public function max(string $field): static + { + $this->select[] = 'MAX(' . $field . ') AS ' . $field; + return $this; + } + + /** + * @param string $lngField + * @param string $latField + * @param int $lng1 + * @param int $lat1 + * + * @return $this + */ + public function distance(string $lngField, string $latField, int $lng1, int $lat1): static + { + $sql = "ROUND(6378.138 * 2 * ASIN(SQRT(POW(SIN(($lat1 * PI() / 180 - $lat1 * PI() / 180) / 2),2) + COS($lat1 * PI() / 180) * COS($latField * PI() / 180) * POW(SIN(($lng1 * PI() / 180 - $lngField * PI() / 180) / 2),2))) * 1000) AS distance"; + $this->select[] = $sql; + return $this; + } + + /** + * @param string|array $column + * @param string $sort + * + * @return $this + * + * [ + * 'addTime', + * 'descTime desc' + * ] + */ + public function orderBy(string|array $column, string $sort = 'DESC'): static + { + if (empty($column)) { + return $this; + } + if (is_string($column)) { + return $this->addOrder(...func_get_args()); + } + + foreach ($column as $val) { + $this->addOrder($val); + } + + return $this; + } + + /** + * @param string $column + * @param string $sort + * + * @return $this + * + */ + private function addOrder(string $column, string $sort = 'DESC'): static + { + if (func_num_args() == 1 || str_contains($column, ' ')) { + $this->order[] = $column; + } else { + $this->order[] = "$column $sort"; + } + return $this; + } + + /** + * @param array|string $column + * + * @return $this + */ + public function select(array|string $column = '*'): static + { + if ($column == '*') { + $this->select = [$column]; + } else { + if (!is_array($column)) { + $column = explode(',', $column); + } + foreach ($column as $val) { + $this->select[] = $val; + } + } + return $this; + } + + /** + * @return $this + */ + public function orderRand(): static + { + $this->order[] = 'RAND()'; + return $this; + } + + /** + * @param array|Closure|string $conditionArray + * @param string $opera + * @param null $value + * @return QueryTrait + * @throws + */ + public function whereOr(array|Closure|string $conditionArray = [], string $opera = '=', $value = null): static + { + if ($conditionArray instanceof Closure) { + $conditionArray = $this->makeClosureFunction($conditionArray); + } + + if (func_num_args() > 1) { + [$conditionArray, $opera, $value] = $this->opera(...func_get_args()); + + $conditionArray = $this->sprintf($conditionArray, $value, $opera); + } + + $this->where = ['((' . implode(' AND ', $this->where) . ') OR (' . $conditionArray . '))']; + return $this; + } + + + /** + * @param string $column + * @param string $value + * @return $this + */ + public function whereLike(string $column, string $value): static + { + $this->bindParam(':LIKE' . $column, $value); + $this->where[] = $column . ' LIKE \':LIKE' . $column . '\''; + return $this; + } + + /** + * @param string $column + * @param string $value + * @return $this + */ + public function whereLeftLike(string $column, string $value): static + { + $this->bindParam(':LLike' . $column, $value); + $this->where[] = $column . ' LLike \'%:LLike' . $column . '\''; + return $this; + } + + /** + * @param string $column + * @param string $value + * @return $this + */ + public function whereRightLike(string $column, string $value): static + { + $this->bindParam(':RLike' . $column, $value); + $this->where[] = $column . ' RLike \':RLike' . $column . '%\''; + return $this; + } + + + /** + * @param string $column + * @param string $value + * @return $this + */ + public function whereNotLike(string $column, string $value): static + { + $this->bindParam(':LIKE' . $column, $value); + $this->where[] = $column . ' NOT LIKE \'%:LIKE' . $column . '%\''; + return $this; + } + + + /** + * @param string $columns + * @param array|Closure $value + * @return $this + * @throws + */ + public function whereIn(string $columns, array|Closure $value): static + { + if ($value instanceof Closure) { + $value = $this->makeClosureFunction($value); + } + if (count($value) < 1) { + $value = [-1]; + } + $this->where[] = $columns . ' IN (' . implode(',', $value) . ')'; + return $this; + } + + + /** + * @param $value + * @return ActiveQuery + * @throws + */ + public function makeNewQuery($value): ActiveQuery + { + $activeQuery = new ActiveQuery($this->modelClass); + call_user_func($value, $activeQuery); + if (empty($activeQuery->from)) { + $activeQuery->from($activeQuery->modelClass->getTable()); + } + return $activeQuery; + } + + + /** + * @return Query + * @throws + */ + public function makeNewSqlGenerate(): Query + { + return Kiri::createObject(['class' => Query::class]); + } + + + /** + * @param string $columns + * @param array $value + * @return $this + */ + public function whereNotIn(string $columns, array $value): static + { + if (count($value) < 1) { + $value = [-1]; + } + $this->where[] = $columns . ' NOT IN (' . implode(',', $value) . ')'; + return $this; + } + + /** + * @param string $column + * @param int $start + * @param int $end + * @return $this + */ + public function whereBetween(string $column, int $start, int $end): static + { + if (empty($column) || empty($start) || empty($end)) { + return $this; + } + + $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; + } + + /** + * @param string $column + * @param int $start + * @param int $end + * @return $this + */ + public function whereNotBetween(string $column, int $start, int $end): static + { + if (empty($column) || empty($start) || empty($end)) { + return $this; + } + + $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; + } + + /** + * @param array|null $params + * + * @return $this + */ + public function bindParams(?array $params = []): static + { + if ($params === null) { + return $this; + } + $this->attributes = array_merge($this->attributes, $params); + return $this; + } + + /** + * @param string $key + * @param mixed $value + * @return $this + */ + public function bindParam(string $key, mixed $value): static + { + if (is_string($value)) { + $value = addslashes($value); + } + $this->attributes[$key] = $value; + return $this; + } + + /** + * @param array $column + * @return $this + */ + public function where(array $column): static + { + return $this->addArray($column); + } + + + /** + * @param string $column + * @param string $opera + * @param mixed $value + * @return $this + */ + public function whereMath(string $column, string $opera, mixed $value): static + { + $this->bindParam(':' . $column, $value); + $this->where[] = $column . ' ' . $opera . ':' . $column; + return $this; + } + + + /** + * @param Closure $closure + * @return $this + */ + public function whereClosure(Closure $closure): static + { + $this->where[] = $this->makeClosureFunction($closure); + return $this; + } + + + /** + * @param Closure|array $closure + * @return string + * @throws + */ + public function makeClosureFunction(Closure|array $closure): string + { + $generate = $this->makeNewSqlGenerate(); + if ($closure instanceof Closure) { + call_user_func($closure, $generate); + } else { + $generate->addArray($closure); + } + return $generate->getSql(); + } + + + /** + * @param string $name + * @param string|null $having + * + * @return $this + */ + public function groupBy(string $name, string $having = NULL): static + { + $this->group = $name; + if (empty($having)) { + return $this; + } + $this->group .= ' HAVING ' . $having; + return $this; + } + + /** + * @param int $limit + * + * @return $this + */ + public function limit(int $limit = 20): static + { + $this->limit = $limit; + return $this; + } + + + /** + * @param int $offset + * @return $this + */ + public function offset(int $offset): static + { + $this->offset = $offset; + return $this; + } + + + /** + * @return array + */ + private function opera(): array + { + if (func_num_args() == 3) { + [$column, $opera, $value] = func_get_args(); + } else { + [$column, $value] = func_get_args(); + } + if (!isset($opera)) { + $opera = '='; + } + return [$column, $opera, $value]; + } + + + /** + * @param array $array + * @return $this + */ + private function addArray(array $array): static + { + foreach ($array as $key => $value) { + if ($value === null) { + continue; + } + $this->where[] = $this->sprintf($key, $value); + } + return $this; + } + + + /** + * @param $column + * @param $value + * @param string $opera + * @return string + */ + private function sprintf($column, $value, string $opera = '='): string + { + $this->bindParam(':' . $column, $value); + return $column . ' ' . $opera . ' :' . $column; + } + + + /** + * @return $this + */ + public function oneLimit(): static + { + $this->limit = 1; + return $this; + } } diff --git a/Traits/When.php b/Traits/When.php index 35c959a..702dc53 100644 --- a/Traits/When.php +++ b/Traits/When.php @@ -54,8 +54,8 @@ class When /** * @param string $alias */ - public function else(string $alias) - { + public function else(string $alias): void + { $this->else = $alias; }