6

次のテーブル構造がありますが、これも便宜上sqlfiddleにあります。

+---------+-----------+---------+----------+------ ---+---------------------------------+------------------------ -----------+--------+--------------+-------------+ ---------------+-----------+
| | ルール ID | 親 ID | left_id | right_id | ルールの種類 | ルールタイトル | ルールの説明 | 公開 | parse_bbcode | parse_links | parse_smilies | グループ ID |
+---------+-----------+---------+----------+------ ---+---------------------------------+------------------------ -----------+--------+--------------+-------------+ ---------------+-----------+
| | 1 | 0 | 1 | 6 | 猫 | 猫 | サンプル カテゴリ 1 | | | 1 | 0 | 0 | 0 | 1 2 7 |
| | 2 | 1 | 2 | 3 | ルール | サンプル ルール 1 | これはルールの説明のサンプルです | 1 | 1 | 1 | 1 | 1 2 7 |
| | 3 | 0 | 7 | 8 | 猫 | 猫 | サンプル カテゴリ 2 | | | 1 | 0 | 0 | 0 | 1 7 2 |
| | 4 | 0 | 9 | 10 | 猫 | 猫 | サンプル カテゴリ 3 | | | 1 | 0 | 0 | 0 | 1 7 2 |
| | 5 | 1 | 4 | 5 | ルール | サンプル ルール 3 | 笑 | 1 | 1 | 1 | 1 | 1 2 7 |
+---------+-----------+---------+----------+------ ---+---------------------------------+------------------------ -----------+--------+--------------+-------------+ ---------------+-----------+

ご覧のとおり、 または のrule_typeいずれ'cat'かになります'rule'

catカテゴリを表し、カテゴリはルートノードです。parent_id常にそう0です。私のコードでは、 ifrule_type = 'cat'またはをチェックすることでカテゴリを識別できますparent_id = 0

また、プロジェクトにネストされたセットを使用していることもわかりますが、これが問題の原因です。

次の機能を正常に作成しました。

  • ルールとカテゴリを上下に移動します。と

  • それぞれの場所の最後に新しいルールまたはカテゴリを配置します。

しかし、ルールの 設定に失敗していますright_id&left_idそのを変更した場合parent_id! ルールまたはカテゴリを削除すると、right_id&の設定にも失敗します。left_id

例を挙げて説明しようと思います。これは単なる例であり、実際のケースではないことに注意してください。一般的な回答が必要です。

rule_id IN (1, 3, 4)上の表から、 の 3 つのカテゴリと の 2 つのルールがあることがわかりますrule_id IN (2, 5)

ルールrule_id = 2のカテゴリの一部です。列rule_id = 1から確認できます。parent_idを 4に変更するとどうparent_idなりますか? right_id&はどのようleft_idに設定されるので、すべてが再び適切に配置されますか? すべてを並べ替えるには両方を更新する必要があるrule_id IN (1, 4)ことはわかっていますが、クエリがどのようになるかわかりません。

削除についても同じことが言えます...たとえば、削除しますrule_id = 2(これはルールです)、正しい順序でright_id&left_idを設定するにはどうすればよいですか? parent_id = 1または、カテゴリを削除するときは?カテゴリを並べ替えるにはどうすればよいですか?

どうやってそのようなことをするかについてのビジョンがないので、私はここで何もしようとはしませんでした。

私は自分自身を明確にしたことを願っています。そうでない場合はお知らせください。さらに詳しく説明します。

4

2 に答える 2

7

PDO 接続が正常にセットアップされたと仮定します。

また、次の例は、すべてのカテゴリがルート ノード (件名のように) である場合にのみ機能することに注意してください。ネストされたカテゴリで動作するようにこのコードを変更しても問題ありません。

ルールの削除

  1. その値を取得しright_idますleft_id

  2. データベースから行を削除します。

  3. テーブル セットを更新しますright_id- 2 の場合、削除ルールのright_idより大きくなります。right_id

  4. 同じ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

ノードを新しい親の最後の位置に移動するとします。

  1. 更新ルールのleft_idand right_id( $ruleLeftIdand $ruleRightId)を取得します

  2. 新しい親ルールのleft_idand right_id( $newParentRuleLeftIdand $newParentRuleRightId)を取得します

  3. ノードがツリーを上下に移動するかどうかを確認し、それに応じて、更新ルールの新しいleft_idとの値を生成します (と)right_id$ruleNewLeftId$ruleNewRightId

  4. ルールを更新し、更新ルールの宛先left_idright_id応じて

  5. 更新規則の更新parent_idleft_idright_id

更新ルールがright_key新しい親ルールよりも小さい場合、right_idルールはツリーを下に移動し、そうでない場合はツリーを上に移動します。

ルールがツリーを下に移動する場合、left_id更新ルールのleft_id( $ruleLeftId) と new left_id( $ruleNewLeftId) + 1 の間にあるルールで値をマイナス 2 シフトします。そうでない場合は、new ($ruleNewLeftId) と new ($ruleNewLeftId)left_idの間にあるルールで値を 2シフトしますleft_idイニシャル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;
    }

PDO::Statementスペースを節約するためだけに使用しませんでした。

私はそれを適切にテストしていないので、見つけた場合は問題を投稿してください。

于 2012-10-29T11:08:37.257 に答える
1

rule_id = 2 のルールは、rule_id = 1 のカテゴリの一部であり、parent_id 列から確認できます。parent_id を 4 に変更するとどうなりますか? right_id と 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)
于 2012-10-25T17:11:55.900 に答える