GetRows(fn (DBItemProperty $property): bool => $property->IsPrimaryKey); // Создаю условие по первичным ключам (оно же и WHERE для обновления) $where = new ConditionBuilder(); // Для каждого первичного ключа for ($i = 0; $i < $primaryKeys->Count(); $i++) { // - если это не первая итерация if ($i > 0) // -- то добавляю AND $where = $where->And(); /** * Получаю свойство. * * @var DBItemProperty $property Свойство. */ $property = $primaryKeys[$i]; // - получаю ключ $whereKey = $property->FieldName; // - получаю значение ключа, конвертируя его в БД $whereValue = call_user_func($property->ConvertToDB, $property->Value); // - добавляю условие в WHERE $where = $where->WhereEquals($whereKey, $whereValue); } // Получаю запись из базы данных $dbItem = $this->GetRow($table, $where, className: get_class($item)); // Если запись не найдена if ($dbItem === false) // - то и общий результат - false return false; // Создаю массив параметров для обновления $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 ($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; } /** * Обновляет несколько записей в таблице базы данных. * * @param string $table Имя таблицы. * @param IDBItem ...$items Массив обновляемых объектов. * * @return bool Результат выполнения. */ public function UpdateMany (string $table, IDBItem ...$items): bool { // Инициализирую транзакцию $this->InitTransaction(); // Подготавливаю массив последних id $resultArray = []; try { // Для каждого источника foreach ($items as $item) // - вставляю строку $resultArray[] = $this->Update($table, $item); // Если вставка успешна, то подтверждаю транзакцию $this->Commit(); } catch (Exception) { // - если ошибка, то откатываю транзакцию $this->RollBack(); // - и вывожу ошибку return false; } // Если есть ошибка if (array_any($resultArray, fn (bool $value): bool => $value === false)) // - то вывожу ошибку return false; // Так как мы дошли до сюда, то это успех! Вывожу результат return true; } }