From a80c4e6f65be19d9f446c08c3bbb25e5392affc4 Mon Sep 17 00:00:00 2001 From: babaev-an Date: Sat, 2 Aug 2025 21:20:32 +0300 Subject: [PATCH] 20250802-1 --- .gitignore | 23 +- sources/attributes/ConvertToDB.php | 9 +- sources/classes/DBItemProperty.php | 92 +++++++ sources/classes/Database.php | 46 +--- sources/traits/Database/DatabaseDelete.php | 64 +++++ sources/traits/Database/DatabaseSpecial.php | 257 +++++++------------- sources/traits/Database/DatabaseUpdate.php | 226 ++++++++++------- 7 files changed, 402 insertions(+), 315 deletions(-) create mode 100644 sources/classes/DBItemProperty.php create mode 100644 sources/traits/Database/DatabaseDelete.php diff --git a/.gitignore b/.gitignore index e1118fb..d742510 100644 --- a/.gitignore +++ b/.gitignore @@ -398,8 +398,6 @@ node_modules/ *.dsp # Visual Studio 6 technical files -*.ncb -*.aps # Visual Studio LightSwitch build output **/*.HTMLClient/GeneratedArtifacts @@ -473,15 +471,9 @@ MigrationBackup/ FodyWeavers.xsd # VS Code files for those working on multiple tools -.vscode/* -!.vscode/settings.json -!.vscode/tasks.json -!.vscode/launch.json -!.vscode/extensions.json *.code-workspace # Local History for Visual Studio Code -.history/ # Windows Installer files from build outputs *.cab @@ -2221,3 +2213,18 @@ FodyWeavers.xsd /vendor/goodboyalex/php_components_pack/ /.idea/php-test-framework.xml /.idea/inspectionProfiles/Project_Default.xml +/vendor/phpunit/phpunit/schema/12.2.xsd +/vendor/phpunit/phpunit/src/TextUI/Configuration/BootstrapLoader.php +/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/BootstrapScriptDoesNotExistException.php +/vendor/phpunit/phpunit/src/TextUI/Configuration/Exception/BootstrapScriptException.php +/vendor/phpunit/phpunit/ChangeLog-12.3.md +/vendor/phpunit/phpunit/src/Event/Events/TestRunner/ChildProcessErrored.php +/vendor/phpunit/phpunit/src/Event/Events/TestRunner/ChildProcessErroredSubscriber.php +/vendor/phpunit/phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/ChildProcessErroredSubscriber.php +/vendor/phpunit/phpunit/src/Runner/CodeCoverageInitializationStatus.php +/vendor/phpunit/phpunit/src/Framework/Attributes/IgnorePhpunitWarnings.php +/vendor/phpunit/phpunit/src/Metadata/IgnorePhpunitWarnings.php +/vendor/phpunit/phpunit/src/Metadata/Api/ProvidedData.php +/vendor/phpunit/phpunit/src/Framework/Attributes/TestDoxFormatter.php +/vendor/phpunit/phpunit/src/Metadata/TestDoxFormatter.php +/vendor/phpunit/phpunit/src/Framework/Attributes/TestDoxFormatterExternal.php \ No newline at end of file diff --git a/sources/attributes/ConvertToDB.php b/sources/attributes/ConvertToDB.php index 8ce37e4..34f23da 100644 --- a/sources/attributes/ConvertToDB.php +++ b/sources/attributes/ConvertToDB.php @@ -31,15 +31,22 @@ */ public ?Closure $ConvertFromDB; + /** + * @var Closure|null Метод сравнения типов. + */ + public ?Closure $Compare; + /** * Конструктор. * * @param callable|null $fromType Метод конвертации из типа для заполнения таблицы базы данных. * @param callable|null $toType Метод конвертации в тип для заполнения таблицы базы данных. + * @param callable|null $compare Метод сравнения типов. */ - public function __construct (?callable $fromType = null, ?callable $toType = null) + public function __construct (?callable $fromType = null, ?callable $toType = null, ?callable $compare = null) { $this->ConvertToDB = $fromType; $this->ConvertFromDB = $toType; + $this->Compare = $compare; } } \ No newline at end of file diff --git a/sources/classes/DBItemProperty.php b/sources/classes/DBItemProperty.php new file mode 100644 index 0000000..d1db85c --- /dev/null +++ b/sources/classes/DBItemProperty.php @@ -0,0 +1,92 @@ +Name = $name; + // - установка значения свойства (ещё не конвертированного) + $this->Value = $value; + // - установка имени поля в таблице БД + $this->FieldName = StringExtension::IsNullOrWhitespace($fieldName) ? $name : $fieldName; + // - установка признака того, что свойство является первичным ключом + $this->IsPrimaryKey = $isPrimaryKey; + // - установка признака того, что свойство игнорируется при сохранении в / загрузке из БД + $this->IsIgnored = $isIgnored; + // - установка конвертеров значения свойства в значение поля БД + $this->ConvertToDB = $ConvertToDB ?? fn (mixed $value): mixed => $value; + // - установка конвертеров значения поля БД в значение свойства + $this->ConvertFromDB = $ConvertFromDB ?? fn (mixed $value): mixed => $value; + // - установка функции сравнения значений свойства + $this->Compare = $Compare ?? fn (mixed $value1, mixed $value2): bool => $value1 == $value2; + } + } \ No newline at end of file diff --git a/sources/classes/Database.php b/sources/classes/Database.php index e50ddc7..c2fdd9d 100644 --- a/sources/classes/Database.php +++ b/sources/classes/Database.php @@ -10,6 +10,7 @@ use goodboyalex\php_db_components_pack\enums\DBDriver; use goodboyalex\php_db_components_pack\models\DBConfig; use goodboyalex\php_db_components_pack\traits\Database\DatabaseCountExist; + use goodboyalex\php_db_components_pack\traits\Database\DatabaseDelete; use goodboyalex\php_db_components_pack\traits\Database\DatabaseGet; use goodboyalex\php_db_components_pack\traits\Database\DatabaseInsert; use goodboyalex\php_db_components_pack\traits\Database\DatabaseQueryExecute; @@ -150,48 +151,9 @@ // Обновление записей use DatabaseUpdate; + // Удаление записей + use DatabaseDelete; + // Приватные методы use DatabaseSpecial; - - /** - * Удаляет строки по условию. - * - * @param string $table Имя таблицы - * @param array $where Массив условий - * - * @return bool Результат выполнения - */ - public function Delete (string $table, array $where = []): bool - { - // Обработанные параметры - $params = []; - - // Строковая интерпретация массива условий - $sql_where = $this->PrepareQueryWhere(where: $where, params: $params); - - // Создаю запрос - $sql = "DELETE FROM $this->DBSignOpen$table$this->DBSignClose"; - - // Если заданы where-параметры - if (count($where) > 0) { - // - то добавляю их - $sql .= " WHERE $sql_where"; - } - - // Выполняю запрос - $count = $this->Execute($sql, $params); - - // Если результат - false - if ($count === false) - // - то и общий результат - false - return false; - - // Если изменено 0 строк - if ($count === 0) - // - то и общий результат - false - return false; - - // Вывожу результат -- успех - return true; - } } \ No newline at end of file diff --git a/sources/traits/Database/DatabaseDelete.php b/sources/traits/Database/DatabaseDelete.php new file mode 100644 index 0000000..2b22ea9 --- /dev/null +++ b/sources/traits/Database/DatabaseDelete.php @@ -0,0 +1,64 @@ +Build(); + + // Создаю запрос + $sql = "DELETE FROM $this->DBSignOpen$table$this->DBSignClose"; + + // Если заданы where-параметры + if ($where->Count() > 0) + // - то добавляю их + $sql .= " WHERE $sql_where"; + + // Выполняю запрос + $count = $this->Execute($sql, $params); + + // Если результат - false + if ($count === false) + // - то и общий результат - false + return false; + + // Если изменено 0 строк + if ($count === 0) + // - то и общий результат - false + return false; + + // Вывожу результат -- успех + return true; + } + } \ No newline at end of file diff --git a/sources/traits/Database/DatabaseSpecial.php b/sources/traits/Database/DatabaseSpecial.php index 3153606..236782b 100644 --- a/sources/traits/Database/DatabaseSpecial.php +++ b/sources/traits/Database/DatabaseSpecial.php @@ -7,17 +7,18 @@ namespace goodboyalex\php_db_components_pack\traits\Database; use Exception; + use goodboyalex\php_components_pack\classes\ObjectArray; use goodboyalex\php_db_components_pack\attributes\ConvertToDB; use goodboyalex\php_db_components_pack\attributes\FieldName; use goodboyalex\php_db_components_pack\attributes\IgnoredInDB; use goodboyalex\php_db_components_pack\attributes\PrimaryKey; use goodboyalex\php_db_components_pack\classes\ConditionBuilder; + use goodboyalex\php_db_components_pack\classes\DBItemProperty; use goodboyalex\php_db_components_pack\enums\DBOperation; use goodboyalex\php_db_components_pack\interfaces\IDBItem; use PDO; use ReflectionClass; use ReflectionException; - use ReflectionProperty; /** * Трейт для функций поддержки для работы с базой данных. @@ -44,73 +45,45 @@ } /** - * Получает публичные свойства класса и их значения. + * Разбирает объект на свойства. * - * @param object $obj Класс. + * @param IDBItem $source Объект со свойствами. + * @param DBOperation $operation Текущая операция. * - * @return array Массив публичных свойств и их значений. + * @return ObjectArray Массив свойств и их значений класса, который реализует интерфейс IDBItem. */ - private static function GetPublicProperties (object $obj): array + private static function GetProperties (IDBItem $source, DBOperation $operation): ObjectArray { // Создаю массив свойств - $result = []; + $result = new ObjectArray(); // Получаю массив свойств - $properties = get_class_vars(get_class($obj)); + $properties = get_class_vars(get_class($source)); // Для каждого свойства foreach ($properties as $key => $value) { // - пропускаю не свойства - if (!property_exists($obj, $key)) + if (!property_exists($source, $key)) // -- пропускаю continue; - // - получаю рефлексию - $rProperty = new ReflectionProperty($obj, $key); - - // - пропускаю не публичные свойства - if (!$rProperty->isPublic()) - // -- пропускаю - continue; - - // - добавляю в массив свойство и его значение - $result[$key] = $value; - } - - // Возвращаю результат - return $result; - } - - /** - * Получает первичные ключи класса. - * - * @param IDBItem $source Класс. - * @param DBOperation $operation Текущая операция. - * - * @return array Массив первичных ключей и их значений. - */ - private function FindPrimaryKeys (IDBItem $source, DBOperation $operation): array - { - // Создаю массив первичных ключей - $pKeys = []; - - // Получаю массив свойств - $properties = self::GetPublicProperties($source); - - // Для каждого свойства - foreach ($properties as $key => $value) { - // - получаю рефлексию - // - для класса + // - получаю рефлексию класса $reflectedClass = new ReflectionClass(get_class($source)); + try { - // - для свойства + // - получаю рефлексию свойства $reflectionProperty = $reflectedClass->getProperty($key); } catch (ReflectionException) { // - если ошибка, то вывожу пустой массив - return []; + return $result; } + // - пропускаю не публичные свойства + if (!$reflectionProperty->isPublic()) + // -- пропускаю + continue; + // - получаю атрибуты $attributes = $reflectionProperty->getAttributes(); @@ -121,10 +94,8 @@ */ $pkAttr = self::FindAttribute($attributes, PrimaryKey::class); - // - если на свойстве нет атрибута первичного ключа - if ($pkAttr === null) - // -- то пропускаю - continue; + // - это первичный ключ? + $isPrimary = $pkAttr !== null; /** * Фильтруем поля, игнорируемые для данной операции @@ -134,22 +105,42 @@ $ignoreAttr = self::FindAttribute($attributes, IgnoredInDB::class); // - если поле игнорируется - if ($ignoreAttr !== null) { - // -- то проверяю, игнорируется ли данное поле - $isIgnore = $ignoreAttr->IgnoredOperations->IsExist(fn (DBOperation $oper) => $oper == $operation); - - // -- если игнорируется - if ($isIgnore) - // --- то пропускаю - continue; - } + $isIgnore = $ignoreAttr !== null + && $ignoreAttr->IgnoredOperations->IsExist(fn (DBOperation $oper) + => $oper == $operation); - // - добавляю первичный ключ и его значение - $pKeys[$key] = $value; + /** + * Получаю значение имени поля + * + * @var FieldName|null $fieldNameAttr Атрибут имени поля. + */ + $fieldNameAttr = self::FindAttribute($attributes, FieldName::class); + + // Если есть атрибут имени поля, то беру его имя, иначе беру имя свойства + $fieldName = $fieldNameAttr !== null ? $fieldNameAttr->FieldName : ""; + + /** + * Преобразование типа. + * + * @var ConvertToDB|null $convertAttr Атрибут конвертации. + */ + $convertAttr = self::FindAttribute($attributes, ConvertToDB::class); + + // - получаю функцию конвертации и сравнения + $converterToDB = $convertAttr?->ConvertToDB; + $converterFromDB = $convertAttr?->ConvertFromDB; + $compareFunc = $convertAttr?->Compare; + + // - создаю объект свойства + $item = new DBItemProperty($key, $value, $fieldName, $isPrimary, $isIgnore, $converterToDB, + $converterFromDB, $compareFunc); + + // - добавляю в массив + $result[] = $item; } - // Возвращаю найденные ключи - return $pKeys; + // Возвращаю результат + return $result; } /** @@ -165,70 +156,25 @@ $result = []; // Получаю массив свойств - $properties = self::GetPublicProperties($source); + $properties = self::GetProperties($source, $operation); - // Для каждого свойства - foreach ($properties as $key => $value) { - // Получаю рефлексию - // - для класса - $reflectedClass = new ReflectionClass(get_class($source)); - try { - // - для свойства - $reflectionProperty = $reflectedClass->getProperty($key); - } - catch (ReflectionException $e) { - // - если ошибка, то вывожу и выходим - $this->HandleException($e); - } + /** + * Для каждого свойства... + * + * @var DBItemProperty $property Свойство. + */ + foreach ($properties as $property) { + // - пропускаю игнорируемые поля + if ($property->IsIgnored) + continue; - // - получаю атрибуты - $attributes = $reflectionProperty->getAttributes(); + // - получаю значение имени поля + $fieldName = $property->FieldName; - /** - * Фильтруем поля, игнорируемые для данной операции - * - * @var IgnoredInDB|null $ignoreAttr Атрибут игнорирования. - */ - $ignoreAttr = self::FindAttribute($attributes, IgnoredInDB::class); + // - преобразую тип + $value = call_user_func($property->ConvertToDB, $property->Value); - // - если поле игнорируется - if ($ignoreAttr !== null) { - // -- то проверяю, игнорируется ли данное поле - $isIgnore = $ignoreAttr->IgnoredOperations->IsExist(fn (DBOperation $oper) => $oper == $operation); - - // -- если игнорируется - if ($isIgnore) - // --- то пропускаю - continue; - } - - /** - * Получаю значение имени поля - * - * @var FieldName|null $fieldNameAttr Атрибут имени поля. - */ - $fieldNameAttr = self::FindAttribute($attributes, FieldName::class); - - // Если есть атрибут имени поля, то беру его имя, иначе беру имя свойства - $fieldName = $fieldNameAttr !== null ? $fieldNameAttr->FieldName : $key; - - /** - * Преобразование типа. - * - * @var ConvertToDB|null $convertAttr Атрибут конвертации. - */ - $convertAttr = self::FindAttribute($attributes, ConvertToDB::class); - - // Если есть атрибут конвертации - if ($convertAttr) { - // - то получаю значение функции конвертации - $converter = $convertAttr->ConvertToDB; - - // - выполняю функцию конвертации - $value = call_user_func($converter, $value); - } - - // Добавляю в массив + // - добавляю в массив $result[$fieldName] = $value; } @@ -255,66 +201,27 @@ // Создаём объект желаемого класса $class = new $className(); - // Получаем публичные свойства класса - try { - $properties = new ReflectionClass($class)->getProperties(ReflectionProperty::IS_PUBLIC); - } - catch (ReflectionException $exception) { - // - в случае ошибки, обрабатываем её - $this->HandleException($exception, false); - - // - и возвращаем null - return null; - } + // Получаю свойства класса + $properties = self::GetProperties($class, $operation); // Массив отношений, содержащий имя поля, имя свойства, метод преобразования $propertiesRelationship = []; - // Для каждого свойства + /** + * Для каждого свойства... + * + * @var DBItemProperty $property Свойство. + */ foreach ($properties as $property) { - // - получаю атрибуты - $attributes = $property->getAttributes(); + // - пропускаю игнорируемые поля + if ($property->IsIgnored) + continue; - /** - * Фильтруем поля, игнорируемые для данной операции - * - * @var IgnoredInDB|null $ignoreAttr Атрибут игнорирования. - */ - $ignoreAttr = self::FindAttribute($attributes, IgnoredInDB::class); - - // - если поле игнорируется - if ($ignoreAttr !== null) { - // -- то проверяю, игнорируется ли данное поле - $isIgnore = $ignoreAttr->IgnoredOperations->IsExist(fn (DBOperation $oper) => $oper == $operation); - - // -- если игнорируется - if ($isIgnore) - // --- то пропускаю - continue; - } - - /** - * Получаю значение имени поля - * - * @var FieldName|null $fieldNameAttr Атрибут имени поля. - */ - $fieldNameAttr = self::FindAttribute($attributes, FieldName::class); - - // - если есть атрибут имени поля, то беру его имя, иначе беру имя свойства - $fieldName = $fieldNameAttr !== null ? $fieldNameAttr->FieldName : $property->getName(); - - /** - * Преобразование типа. - * - * @var ConvertToDB|null $convertAttr Атрибут конвертации. - */ - $convertAttr = self::FindAttribute($attributes, ConvertToDB::class); - - // - если есть атрибут конвертации, то получаю значение функции конвертации, иначе null - $converterFunc = ($convertAttr) ? $convertAttr->ConvertFromDB : null; + // - получаю имя поля + $fieldName = $property->FieldName; // - добавляю в массив отношений - $propertiesRelationship[$fieldName] = [$property->getName(), $converterFunc]; + $propertiesRelationship[$fieldName] = [$property->Name, $property->ConverterFromDB]; } // Проходим элементы массива из БД diff --git a/sources/traits/Database/DatabaseUpdate.php b/sources/traits/Database/DatabaseUpdate.php index d062eba..558fb44 100644 --- a/sources/traits/Database/DatabaseUpdate.php +++ b/sources/traits/Database/DatabaseUpdate.php @@ -5,7 +5,9 @@ namespace goodboyalex\php_db_components_pack\traits\Database; + use Exception; use goodboyalex\php_db_components_pack\classes\ConditionBuilder; + use goodboyalex\php_db_components_pack\classes\DBItemProperty; use goodboyalex\php_db_components_pack\enums\DBOperation; use goodboyalex\php_db_components_pack\interfaces\IDBItem; use PDO; @@ -25,48 +27,128 @@ * Заменяет данные в строке базы данных. * * @param string $table Имя таблицы. - * @param array $set Массив данных для замены - * @param array $where Массив условий + * @param IDBItem $item Обновляемый объект. * - * @return bool Результат выполнения + * @return bool Результат выполнения. */ - public function UpdateOld (string $table, array $set, array $where = []): bool + public function Update (string $table, IDBItem $item): bool { - // Создаю массив параметров - $params_set = []; + // Получаю свойства объекта + $properties = self::GetProperties($item, DBOperation::Update); - // Строковая интерпретация массива для изменения - $sql_set = ""; + // Получаю первичные ключи объекта + $primaryKeys = $properties->GetRows(fn (DBItemProperty $property): bool => $property->IsPrimaryKey); - // Для каждых данных для изменения - foreach ($set as $key => $value) { - // - получаю ключ 100%-но без ":" в начале - $set_key = $key[0] == ":" ? substr($key, 1) : $key; + // Создаю условие по первичным ключам (оно же и WHERE для обновления) + $where = new ConditionBuilder(); + + // Для каждого первичного ключа + for ($i = 0; $i < $primaryKeys->Count(); $i++) { + // - если это не первая итерация + if ($i > 0) + // -- то добавляю AND + $where = $where->And(); - // - добавляю префикс для 2 или более итерации - $prefix = $sql_set == "" ? "" : ", "; + /** + * Получаю свойство. + * + * @var DBItemProperty $property Свойство. + */ + $property = $primaryKeys[$i]; - // - добавляю данные в sql_set - $sql_set .= "$prefix$this->DBSignOpen$set_key$this->DBSignClose=:$set_key"; + // - получаю ключ + $whereKey = $property->FieldName; - // - добавляю данные в параметры - $params_set[":" . $set_key] = $value; + // - получаю значение ключа, конвертируя его в БД + $whereValue = call_user_func($property->ConvertToDB, $property->Value); + + // - добавляю условие в WHERE + $where = $where->WhereEquals($whereKey, $whereValue); } - // Обработанные параметры - $params_where = []; + // Получаю запись из базы данных + $dbItem = $this->GetRow($table, $where, className: get_class($item)); - // Строковая интерпретация массива условий - $sql_where = $this->PrepareQueryWhere(where: $where, params: $params_where); + // Если запись не найдена + if ($dbItem === false) + // - то и общий результат - false + return false; - // Создаю параметры - $params = array_merge($params_set, $params_where); + // Создаю массив параметров для обновления + $propertyToSet = []; + + /** + * Для каждого свойства... + * + * @var DBItemProperty $property Свойство. + */ + foreach ($properties as $property) { + // ... если это первичный ключ + if ($property->IsPrimaryKey) + // - то пропускаю его + continue; + + // ... если свойство игнорируется + if ($property->IsIgnored) + // - то пропускаю его + continue; + + // - получаю значение из базы данных + $inDBValue = $dbItem->{$property->Name}; + + /** + * Получаю результат сравнения текущего значения и значения из базы данных. + * + * @var bool $compareResult Результат сравнения. + */ + $compareResult = call_user_func($property->Compare, $inDBValue, $property->Value); + + // - если значения не изменилось + if ($compareResult) + // -- то и обновлять его не нужно + continue; + + // - конвертирую значение в БД + $value = call_user_func($property->ConvertToDB, $property->Value); + + // - добавляю его в массив параметров для обновления + $propertyToSet[$property->FieldName] = $value; + } + + // Создаю массив set + $set = []; + + // Создаю массив параметров set для обновления + $set_params = []; + + // Для каждого свойства для обновления + foreach ($propertyToSet as $key => $value) { + // - добавляю его в массив set + $set[] = "$this->DBSignOpen$key$this->DBSignClose=:$key"; + + // - добавляю его в массив параметров set для обновления + $set_params[":$key"] = $value; + } + + // Строковая интерпретация массива set + $sql_set = count($set) > 0 ? '(' . implode(", ", $set) . ')' : ""; + + /** + * Получаю WHERE-запрос и параметры. + * + * @var string $sql_where WHERE-запрос. + * @var array $where_params Параметры WHERE-запроса. + */ + [$sql_where, $where_params] = $where->Build(); + + // Объединяю все параметры в один массив + $params = array_merge($set_params, $where_params); // Создаю запрос $sql = "UPDATE $this->DBSignOpen$table$this->DBSignClose SET $sql_set"; // Если заданы where-параметры - if (count($where) > 0) + if ($where->Count() > 0) // - то добавляю их $sql .= " WHERE $sql_where"; @@ -87,79 +169,45 @@ return true; } - public function Update (string $table, IDBItem $item): bool + /** + * Обновляет несколько записей в таблице базы данных. + * + * @param string $table Имя таблицы. + * @param IDBItem ...$items Массив обновляемых объектов. + * + * @return bool Результат выполнения. + */ + public function UpdateMany (string $table, IDBItem ...$items): bool { - $primaryKeys = $this->FindPrimaryKeys($item, DBOperation::Update); + // Инициализирую транзакцию + $this->InitTransaction(); - $pk_keys = array_keys($primaryKeys); + // Подготавливаю массив последних id + $resultArray = []; - $where = new ConditionBuilder(); - - for ($i = 0; $i < count($primaryKeys); $i++) { - if ($i > 0) - $where = $where->And(); + try { + // Для каждого источника + foreach ($items as $item) + // - вставляю строку + $resultArray[] = $this->Update($table, $item); - $whereKey = $pk_keys[$i]; + // Если вставка успешна, то подтверждаю транзакцию + $this->Commit(); + } + catch (Exception) { + // - если ошибка, то откатываю транзакцию + $this->RollBack(); - $whereValue = $primaryKeys[$whereKey]; - - $where = $where->WhereEquals($whereKey, $whereValue); + // - и вывожу ошибку + return false; } - $dbItem = $this->GetRow($table, $where, className: get_class($item)); - - // Создаю массив параметров - $params_set = []; - - // Строковая интерпретация массива для изменения - $sql_set = ""; - - // Для каждых данных для изменения - foreach ($set as $key => $value) { - // - получаю ключ 100%-но без ":" в начале - $set_key = $key[0] == ":" ? substr($key, 1) : $key; - - // - добавляю префикс для 2 или более итерации - $prefix = $sql_set == "" ? "" : ", "; - - // - добавляю данные в sql_set - $sql_set .= "$prefix$this->DBSignOpen$set_key$this->DBSignClose=:$set_key"; - - // - добавляю данные в параметры - $params_set[":" . $set_key] = $value; - } - - // Обработанные параметры - $params_where = []; - - // Строковая интерпретация массива условий - $sql_where = $this->PrepareQueryWhere(where: $where, params: $params_where); - - // Создаю параметры - $params = array_merge($params_set, $params_where); - - // Создаю запрос - $sql = "UPDATE $this->DBSignOpen$table$this->DBSignClose SET $sql_set"; - - // Если заданы where-параметры - if (count($where) > 0) - // - то добавляю их - $sql .= " WHERE $sql_where"; - - // Выполняю запрос - $count = $this->Execute($sql, $params); - - // Если результат - false - if ($count === false) - // - то и общий результат - false + // Если есть ошибка + if (array_any($resultArray, fn (bool $value): bool => $value === false)) + // - то вывожу ошибку return false; - // Если изменено 0 строк - if ($count === 0) - // - то и общий результат - false - return false; - - // Вывожу результат -- успех + // Так как мы дошли до сюда, то это успех! Вывожу результат return true; } } \ No newline at end of file