tldr (короткая версия): Есть ли более эффективный способ сделать так, чтобы мой запрос на обновление левых значений не завершился неудачей и разрушил транзакцию, если не осталось левых значений для обновления?
Долгосрочная версия, если нужно больше информации. В противном случае пропустите код ниже:
Поэтому я использую PDO и создаю класс категорий для обработки своего вложенного набора, таблицы иерархических категорий. Я готовлю свои операторы для последующего выполнения в транзакции (см. Ниже), НО транзакция продолжает сбой, если я пытаюсь добавить дочерние элементы к определенным узлам, потому что не осталось левого значения для обновления. Это решение, которое я придумал, однако мне интересно, есть ли гораздо лучший способ сделать это. Способ не пометить транзакцию как неудачную, если не найдено левого значения, большего, чем узел сравнения.
левое значение проверяет, являются ли все остальные значения от узла сравнения (куда я хочу вставить) до конца проверенного набора (правильное значение $ base_node) правильными. Если это так, это означает, что для обновления нет левого значения (что может привести к сбою транзакции), и вместо этого SQL2 становится подставным в запросе выбора вместо запроса на обновление). Иначе, если есть значения lft для обновления, он обновляет их.
$ compare_node = представление объекта, в котором мы хотим разместить новую категорию (или после, или до).
$ base_node = Базовый, самый верхний узел иерархии (узел с левым значением 1).
$ SQL2 (часть оператора if else) — это основная часть, о которой я думаю, но, будучи новичком в программировании, я открыт для ЛЮБЫХ предложений или критики моего кода 🙂
////////////////UNDER
if ($post_values['new_cat_location'] == "under" && $nRows > 1){
//setup prepared statements for lef and right updates
$sql1 = "UPDATE ".static::$table_name." SET rgt = rgt + 2 WHERE rgt > :compare_lft";
$update_right = $database->connection->prepare($sql1);
$update_right->bindParam(':compare_lft', $compare_node[0]->lft);
if($this->remaining_all_right($compare_node[0]->rgt, $base_node[0]->rgt) && $compare_node[0]->lft + 1 == $compare_node[0]->rgt){
$sql2 = "SELECT * FROM ".static::$table_name." WHERE id=:id";
$update_left = $database->connection->prepare($sql2);
$update_left->bindParam(':id', static::$cat_root );
}else{
$sql2 = "UPDATE ".static::$table_name." SET lft = lft + 2 WHERE lft > :compare_lft";
$update_left = $database->connection->prepare($sql2);
$update_left->bindParam(':compare_lft', $compare_node[0]->lft);
}
//setup prepared statement for insert of new category
$sql3 = "INSERT INTO ".static::$table_name." (cat_names, cat_descriptions, lft, rgt) VALUES (:cat_names, :cat_descriptions, :compare_lft +1, :compare_lft +2)";
$insert_new_cat = $database->connection->prepare($sql3);
$insert_new_cat->bindParam(':cat_names', $post_values['cat_names']);
$insert_new_cat->bindParam(':cat_descriptions', $post_values['cat_descriptions']);
$insert_new_cat->bindParam(':compare_lft', $compare_node[0]->lft);
}
И тогда вот мой код транзакции в случае необходимости.
//###################################################################################################//
//################## TRANSACTIONS BEGIN HERE BASED ON THE STATEMTNTS PREPED ABOVE ###############//
//###################################################################################################//
$database->connection->beginTransaction();
$database->connection->exec('LOCK TABLE '.static::$table_name.' WRITE');
$confirm_compare_node = self::find_by_id($post_values['node_to_compare']);
if($compare_node[0]->lft != $confirm_compare_node[0]->lft || $compare_node[0]->rgt != $confirm_compare_node[0]->rgt){
$error = "The category tree has changed since you started. Please try again";
echo $error;
}else{
$update_right->execute();
unset($sql1);
if(!$update_right->rowCount()){
$database->connection->rollBack();
$error = "Transaction failed: could not update right values";
echo $error;
}else{
$update_left->execute();
unset($sql2);
if(!$update_left->rowCount()){
$database->connection->rollBack();
$error = "Transaction failed: could not update left values";
echo $error;
}else{
$insert_new_cat->execute();
unset($sql3);
if(!$insert_new_cat->rowCount()){
$database->connection->rollBack();
$error = "Could not insert the new Category";
echo $error;
}else{
$database->connection->commit();
$database->connection->exec('UNLOCK TABLE');
//rebuild the levels of the categories
self::rebuild_cat_levels();
return true;
}
}
}
}
Задача ещё не решена.
Других решений пока нет …