我有以下表结构,为方便起见also on sqlfiddle:
+---------+-----------+---------+----------+-----------+-------------------+-----------------------------------+--------+--------------+-------------+---------------+-----------+ | rule_id | parent_id | left_id | right_id | rule_type | rule_title | rule_description | public | parse_bbcode | parse_links | parse_smilies | group_ids | +---------+-----------+---------+----------+-----------+-------------------+-----------------------------------+--------+--------------+-------------+---------------+-----------+ | 1 | 0 | 1 | 6 | cat | Sample Category 1 | | 1 | 0 | 0 | 0 | 1 2 7 | | 2 | 1 | 2 | 3 | rule | Sample Rule 1 | This is a sample rule description | 1 | 1 | 1 | 1 | 1 2 7 | | 3 | 0 | 7 | 8 | cat | Sample category 2 | | 1 | 0 | 0 | 0 | 1 7 2 | | 4 | 0 | 9 | 10 | cat | Sample category 3 | | 1 | 0 | 0 | 0 | 1 7 2 | | 5 | 1 | 4 | 5 | rule | Sample rule 3 | lol | 1 | 1 | 1 | 1 | 1 2 7 | +---------+-----------+---------+----------+-----------+-------------------+-----------------------------------+--------+--------------+-------------+---------------+-----------+
如您所见,rule_type
可以是'cat'
或'rule'
。
cat
代表类别,类别是根节点:因此parent_id
始终为0
。在我的代码中,我们可以通过选中rule_type = 'cat'
还是parent_id = 0
来确定类别。
您还可以看到我正在为项目使用嵌套集,这就是问题所在。
我已成功创建了以下功能:
移动规则&类别向上或向下;以及
将新规则或类别放在各自的位置。
但我未能设置 RULES' right_id
& left_id
如果我们更改其parent_id
!我也未能设置right_id
& left_id
如果我们删除规则或类别。
我将尝试用一个例子来解释。请注意,这只是一个示例,而不是实际情况,我需要一般答案。
从上表中我们看到,我们有3个类别rule_id IN (1, 3, 4)
和两个rule_id IN (2, 5)
规则。
带有rule_id = 2
的规则是rule_id = 1
类别的一部分,我们可以从parent_id
列中看到。如果我将parent_id
更改为4怎么办? right_id
& left_id
设置好所有内容再次到位?我知道我们需要更新rule_id IN (1, 4)
以重新排序所有内容,但我不知道我的查询会是什么样子。
同样适用于删除...例如,我删除rule_id = 2
(这是规则),我该如何设置right_id
& left_id
parent_id = 1
按正确顺序排列?或者当我删除一个类别?我如何重新排序类别?
我并没有真正尝试在这里做任何事情,因为我没有视力如何做这样的事情,所以我在寻求你的帮助,伙计们。
我希望自己清楚明白。如果没有,请告诉我,我会尝试更具描述性。
答案 0 :(得分:7)
我假设您已成功设置PDO连接。
另外,请注意以下示例仅在所有类别都是根节点(如主题中)时才起作用。更改此代码以使用嵌套类别不是问题。
删除规则
检索其right_id
和left_id
值。
从数据库中删除行。
更新表格集right_id
- 2,其中right_id
大于删除规则的right_id
。
left_id
示例:的
$ruleIdForDel = 2;
$leftId = 2;
$rightId = 3;
$pdo->beginTransaction();
try {
$pdo->exec("DELETE FROM rules WHERE rule_id = $ruleIdForDel");
$pdo->exec("UPDATE rules
SET left_id = CASE
WHEN left_id > $leftId THEN left_id - 2
ELSE left_id
END,
right_id = CASE
WHEN right_id > $rightId THEN right_id - 2
ELSE right_id
END");
$pdo->commit();
} catch (Exception $e) {
$pdo->rollBack();
throw $e;
}
更新规则的parent_id
假设我们要将节点移动到新父节点的最后位置
检索更新规则的left_id
和right_id
($ruleLeftId
和$ruleRightId
)
检索新的父规则left_id
和right_id
($newParentRuleLeftId
和$newParentRuleRightId
)
检查节点在树上向上或向下移动的位置,并根据它为更新规则(left_id
和right_id
生成新的$ruleNewLeftId
和$ruleNewRightId
值)
根据更新规则的目的地更新规则left_id
和right_id
更新更新规则的parent_id
,left_id
,right_id
如果更新规则的right_key
少于新的父规则right_id
,则规则向下移动树,否则它会向上移动树。
如果规则向下移动树,我们将在更新规则的left_id
(left_id
)和新{{1}之间的规则上将$ruleLeftId
值减去2 }(left_id
)+ 1.否则,将新$ruleNewLeftId
($ ruleNewLeftId)与初始left_id
(left_id
之间的规则的left_id
值改为2 )。
$ruleLeftId
相同。
示例:的
right_id
我没有使用任何 // Updating rule
$ruleId = 2;
$ruleLeftId = 2;
$ruleRightId = 3;
// New parent rule
$newParentRuleId = 3;
$newParentRuleLeftId = 7;
$newParentRuleRightId = 8;
// Generate new rule's left and right keys
// Moves up
if ($newParentRuleRightId < $ruleRightId) {
$ruleNewLeftId = $newParentRuleRightId;
$ruleNewRightId = $newParentRuleRightId + 1;
// Moves down
} else {
$ruleNewLeftId = $newParentRuleRightId - 2; // 6
$ruleNewRightId = $newParentRuleRightId - 1; // 7
}
$pdo->beginTransaction();
try {
$pdo->exec("UPDATE rules
SET left_id = CASE
/* Moves down */
WHEN $ruleNewRightId > $ruleRightId AND
left_id > $ruleLeftId AND
left_id <= $ruleNewLeftId + 1 THEN left_id - 2
/* Moves up */
WHEN $ruleNewRightId < $ruleRightId AND
left_id >= $ruleNewLeftId AND
left_id < $ruleLeftId THEN left_id + 2
ELSE left_id
END,
right_id = CASE
WHEN $ruleNewRightId > $ruleRightId AND
right_id > $ruleRightId AND
right_id <= $ruleNewRightId THEN right_id - 2
WHEN $ruleNewRightId < $ruleRightId AND
right_id >= $ruleNewLeftId AND
right_id <= $ruleRightId THEN right_id + 2
ELSE right_id
END");
$pdo->exec("UPDATE rules
SET parent_id = $newParentRuleId,
left_id = $ruleNewLeftId,
right_id = $ruleNewRightId
WHERE rule_id = $ruleId");
$pdo->commit();
} catch (Exception $e) {
$pdo->rollBack();
throw $e;
}
来节省空间。
我没有正确测试,所以如果你找到一些问题就发布一个问题。
答案 1 :(得分:1)
rule_id = 2的规则是rule_id = 1的类别的一部分,我们 可以从parent_id列中看到。如果我更改parent_id怎么办? 到4? right_id&amp; left_id得到设置所以一切都在 再来一次?我知道我们需要将rule_id IN(1,4)更新为 重新排序所有内容,但我不知道我的查询会是什么样子。
尝试这样的事情,我还没有测试过,但它可能会让你走上正确的轨道
UPDATE table SET parent_id = 4,
right_id = (CASE WHEN parent_id = 4 THEN 1 END),
left_id = (CASE WHEN parent_id = 4 THEN 2 END)