From ac572cc92b24413860eda8dd1d4c2fc7b798b11e Mon Sep 17 00:00:00 2001 From: User Date: Mon, 13 Jan 2025 04:23:59 +0300 Subject: [PATCH] 20250113#1 --- README.md | 4 +- src/AbstractMysqlRepository.php | 132 ++++++++++++++++++ src/AbstractRepository.php | 96 +++++++++++++ src/Entity/AbstractEntity.php | 14 ++ src/Entity/EntityInterface.php | 18 +++ src/Entity/ValueObjectInterface.php | 10 ++ src/Mysql/Exception/MysqlException.php | 8 -- src/Mysql/MysqlRepositoryInterface.php | 70 ++++++++++ ...sqlStorageData.php => MysqlResultData.php} | 4 +- src/Mysql/MysqlStorage.php | 13 +- src/Mysql/MysqlStorageInterface.php | 8 +- src/RepositoryException.php | 16 +++ src/RepositoryInterface.php | 39 ++++++ 13 files changed, 409 insertions(+), 23 deletions(-) create mode 100644 src/AbstractMysqlRepository.php create mode 100644 src/AbstractRepository.php create mode 100644 src/Entity/AbstractEntity.php create mode 100644 src/Entity/EntityInterface.php create mode 100644 src/Entity/ValueObjectInterface.php delete mode 100644 src/Mysql/Exception/MysqlException.php create mode 100644 src/Mysql/MysqlRepositoryInterface.php rename src/Mysql/{MysqlStorageData.php => MysqlResultData.php} (98%) create mode 100644 src/RepositoryException.php create mode 100644 src/RepositoryInterface.php diff --git a/README.md b/README.md index 0c22641..a0fcf3f 100644 --- a/README.md +++ b/README.md @@ -10,12 +10,12 @@ Stable version composer require rmphp/storage ``` ```bash -composer require rmphp/storage:"^3.0" +composer require rmphp/storage:"^4.0" ``` Dev version contains the latest changes ```bash -composer require rmphp/storage:"3.x-dev" +composer require rmphp/storage:"4.x-dev" ``` diff --git a/src/AbstractMysqlRepository.php b/src/AbstractMysqlRepository.php new file mode 100644 index 0000000..ca4e795 --- /dev/null +++ b/src/AbstractMysqlRepository.php @@ -0,0 +1,132 @@ +fetchOne()) : $result->fetchOne(); + $out = $this->createFromData($class, $val); + } + return $out ?? null; + } + + + /** @inheritDoc */ + public function createListFromResult(string $class, bool|MysqlResultData $result, callable $function = null): array { + if($result instanceof MysqlResultData) { + foreach($result->fetch() as $resultValue) { + $val = (isset($function)) ? $function($resultValue) : $resultValue; + $out[] = $this->createFromData($class, $val); + } + } + return $out ?? []; + } + + + /** @inheritDoc */ + public function getEntityById(int $id, $require = false) { + $this->checkConst(); + if($result = $this->mysql->findById(static::TABLE, $id)) $out = $this->createFromData(static::ENTINY, $result); + if(empty($out) && $require) throw new RepositoryException("Запись не найдена"); + return $out ?? null; + } + + + /** @inheritDoc */ + public function saveEntity(EntityInterface $object, string $table = null) : mixed { + if(!isset($table)){ + $this->checkConst(); + $table = static::TABLE; + } + $in = $this->getProperties($object, function ($value){ + return (is_string($value)) ? $this->mysql->escapeStr($value) : $value; + }); + if(static::DEBUG) {$this->getSaveDebug($object, $in, $table); exit;} + try { + if (!empty($object->getId()) && !empty($this->mysql->findById($table, $object->getId()))) { + $this->mysql->updateById($table, $in, $object->getId()); + return $object->getId(); + } else { + $this->mysql->insert($table, $in); + return (is_string($object->getId())) ? $object->getId() : $this->mysql->mysql()->insert_id; + } + } catch (\Throwable $throwable) {throw new RepositoryException($throwable->getMessage());} + } + + + /** @inheritDoc */ + public function saveGroup(array $objects, string $table = null): array { + if(!isset($table)){ + $this->checkConst(); + $table = static::TABLE; + } + try{ + $this->mysql->mysql()->begin_transaction(); + foreach($objects as $object) $id[] = $this->saveEntity($object, $table); + $this->mysql->mysql()->commit(); + return $id ?? []; + } + catch (\Exception $exception){ + $this->mysql->mysql()->rollback(); + throw new RepositoryException($exception->getMessage()); + } + } + + + /** @inheritDoc */ + public function deleteEntity(EntityInterface $object, string $table = null) : bool { + if(!isset($table)){ + $this->checkConst(); + $table = static::TABLE; + } + if(!empty($object->getId())){ + return $this->mysql->deleteById($table, $object->getId()); + } + return false; + } + + + /** @inheritDoc */ + public function getStorageLogs() : array { + return $this->mysql->getLogs(); + } + + + /** + * @param ...$arg + * @return void + */ + protected function getSaveDebug(...$arg) : void { + if(function_exists('dd')) dd(...$arg); + if(function_exists('vdd')) vdd(...$arg); + var_dump(...$arg); + } + + + /** + * @throws RepositoryException + */ + protected function checkConst(): void { + if(empty(static::TABLE)) throw new RepositoryException("Имя таблицы не задано"); + if(empty(static::ENTINY)) throw new RepositoryException("Не указан объект"); + } + +} diff --git a/src/AbstractRepository.php b/src/AbstractRepository.php new file mode 100644 index 0000000..f090996 --- /dev/null +++ b/src/AbstractRepository.php @@ -0,0 +1,96 @@ +getProperties() as $property) { + // data[propertyName] ?? data[property_name] ?? null + $value = $data[$property->getName()] ?? $data[strtolower(preg_replace("'([A-Z])'", "_$1", $property->getName()))] ?? null; + // если есть внутренний метод (приоритетная обработка) + if(static::$classes[$class]->hasMethod('set'.ucfirst($property->getName()))) $object->{'set'.ucfirst($property->getName())}($value); + // Если тип свойства класс (valueObject) + elseif($property->hasType() && class_exists($property->getType()->getName())) $object->{$property->getName()} = (is_object($value)) ? $value : new ($property->getType()->getName())($value); + // если значения не пустое + elseif(isset($value)) $object->{$property->getName()} = $value; + // если значения может быть пустое + elseif($property->getType()->allowsNull()) $object->{$property->getName()} = null; + } + return $object; + } + catch (ReflectionException $exception) { + throw new RepositoryException($exception->getMessage()); + } + } + + + /** @inheritDoc */ + public function getAllProperties(object $class, callable $method = null) : array { + $properties = $this->initProperties($class); + return (isset($method)) ? array_map($method, $properties) : $properties; + } + + + /** @inheritDoc */ + public function getProperties(object $class, callable $method = null) : array { + $properties = $this->initProperties($class); + foreach ($properties as $fieldName => $value) { + if(isset($value)) $out[$fieldName] = $value; + } + return (isset($method)) ? array_map($method, $out ?? []) : $out ?? []; + } + + + /** + * @param object $class + * @return array + */ + private function initProperties(object $class): array { + $objectData = get_object_vars($class); + foreach ($objectData as $fieldName => $value) + { + // если есть внутренний метод (приоритетная обработка) + if(method_exists($class, 'get'.ucfirst($fieldName))) { + $fieldValue[$fieldName] = $class->{'get'.ucfirst($fieldName)}($value); + } + // если тип свойства класс (valueObject) + elseif($value instanceof ValueObjectInterface) { + $fieldValue[$fieldName] = $value->get(); + } + // если это логическое значение + elseif(is_bool($value)){ + $fieldValue[$fieldName] = (int) $value; + } + // если это дробное число + elseif(is_float($value)) { + $fieldValue[$fieldName] = $value; + } + // если это целое число + elseif(is_int($value)) { + $fieldValue[$fieldName] = $value; + } + // если это строка + elseif(is_string($value)) { + $fieldValue[$fieldName] = $value; + } + // to option_id + $fieldNameSnakeCase = strtolower(preg_replace("'([A-Z])'", "_$1", $fieldName)); + $out[$fieldNameSnakeCase] = $fieldValue[$fieldName] ?? null; + } + return $out ?? []; + } + +} diff --git a/src/Entity/AbstractEntity.php b/src/Entity/AbstractEntity.php new file mode 100644 index 0000000..9c2fb09 --- /dev/null +++ b/src/Entity/AbstractEntity.php @@ -0,0 +1,14 @@ +id)) ? (($this->id instanceof ValueObjectInterface) ? $this->id->get() : $this->id) : null; + } + +} diff --git a/src/Entity/EntityInterface.php b/src/Entity/EntityInterface.php new file mode 100644 index 0000000..6639e60 --- /dev/null +++ b/src/Entity/EntityInterface.php @@ -0,0 +1,18 @@ +result) $this->result->close(); } -} \ No newline at end of file +} diff --git a/src/Mysql/MysqlStorage.php b/src/Mysql/MysqlStorage.php index c0a7c6c..14810d4 100644 --- a/src/Mysql/MysqlStorage.php +++ b/src/Mysql/MysqlStorage.php @@ -111,7 +111,7 @@ class MysqlStorage implements MysqlStorageInterface { /** @inheritDoc */ - public function find(string $sql, int $ln=0, int $numPage=1, int $count=0): bool|MysqlStorageData { + public function find(string $sql, int $ln=0, int $numPage=1, int $count=0): bool|MysqlResultData { if ($ln > 1) { $cnts = (!empty($count)) ? $count : $this->query($sql)->num_rows; @@ -126,18 +126,17 @@ class MysqlStorage implements MysqlStorageInterface { $result = $this->query($sql.$limit); if (!$result || $result->num_rows == 0) return false; - $data = new MysqlStorageData($result); + $data = new MysqlResultData($result); $data->count = $cnts ?? 0; $data->hex = md5($sql); return $data; } /** @inheritDoc */ - public function findOne(string $sql) : bool|array { + public function findOne(string $sql) : bool|MysqlResultData { $result = $this->query($sql." limit 0, 1"); if (!$result || $result->num_rows == 0) return false; - $data = new MysqlStorageData($result); - return $data->fetchOne(); + return new MysqlResultData($result); } /** @inheritDoc */ @@ -145,7 +144,7 @@ class MysqlStorage implements MysqlStorageInterface { $id = (is_numeric($id)) ? (int) $id : $this->escapeStr($id); $result = $this->query("select * from ".$this->escapeStr($table)." where `$name`='$id' limit 0, 1"); if (!$result || $result->num_rows == 0) return false; - $data = new MysqlStorageData($result); + $data = new MysqlResultData($result); return $data->fetchOne(); } @@ -205,4 +204,4 @@ class MysqlStorage implements MysqlStorageInterface { return $out ?? []; } -} \ No newline at end of file +} diff --git a/src/Mysql/MysqlStorageInterface.php b/src/Mysql/MysqlStorageInterface.php index f3bdb32..23f08a9 100644 --- a/src/Mysql/MysqlStorageInterface.php +++ b/src/Mysql/MysqlStorageInterface.php @@ -80,15 +80,15 @@ interface MysqlStorageInterface { * @param int $ln * @param int $numPage * @param int $count - * @return bool|MysqlStorageData + * @return bool|MysqlResultData */ - public function find(string $sql, int $ln = 0, int $numPage = 1, int $count=0) : bool|MysqlStorageData; + public function find(string $sql, int $ln = 0, int $numPage = 1, int $count=0) : bool|MysqlResultData; /** * @param string $sql * @return bool|array */ - public function findOne(string $sql) : bool|array; + public function findOne(string $sql) : bool|MysqlResultData; /** * @param string $table @@ -127,4 +127,4 @@ interface MysqlStorageInterface { * @return string */ public function getLastLog() : string; -} \ No newline at end of file +} diff --git a/src/RepositoryException.php b/src/RepositoryException.php new file mode 100644 index 0000000..16b6250 --- /dev/null +++ b/src/RepositoryException.php @@ -0,0 +1,16 @@ +data = $data; + } + +} diff --git a/src/RepositoryInterface.php b/src/RepositoryInterface.php new file mode 100644 index 0000000..2a956da --- /dev/null +++ b/src/RepositoryInterface.php @@ -0,0 +1,39 @@ +