Dug*_*ugi 6 php mysql database nested-sets sql-update
我有以下表结构,为方便起见,它也在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.在我的代码中,我们可以通过检查if rule_type = 'cat'或来识别类别parent_id = 0.
您还可以看到我正在为我的项目使用嵌套集,这就是问题所在.
我已经成功创建了以下功能:
上下移动规则和类别; 和
将新规则或类别放在各自的位置.
但我不能设置规则" 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正确的顺序?或者当我删除一个类别?我该如何重新排序类别?
我没有真正尝试在这里做任何事情,因为我没有视力如何做这样的事情,所以我要求你的帮助,伙计们.
我希望我清楚自己.如果没有,请告诉我,我会尝试更具描述性.
我假设您已成功设置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;
}
Run Code Online (Sandbox Code Playgroud)
更新规则 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($ruleLeftId)和new left_id($ruleNewLeftId)+ 1 之间的规则上将值减去负2.否则,将新left_id值left_id($ ruleNewLeftId)之间的规则移位2 并且initial left_id($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;
}
Run Code Online (Sandbox Code Playgroud)
我没有使用任何PDO::Statement只是为了节省空间.
我没有正确测试它,所以如果你找到一些问题就发布一个问题.
| 归档时间: |
|
| 查看次数: |
1319 次 |
| 最近记录: |