7

次のテーブルフォルダーがあります。

  id    name    childOf
------------------------
  1      A        0
  2      B        1
  3      C        0
  4      D        3
  5      E        2
  6      F        5

これはツリーを形成します:

A
-B
--E
---F
C
-D

フォルダーのドラッグ アンド ドロップを許可していますが、フォルダーが独自のサブフォルダーにドラッグされないようにする必要があります。

たとえば、D から B は OK、D から E は OK、B から F は独自のツリーにドラッグするので OK ではありませんが、F から B はツリーを上にドラッグするので OK です。

質問: ユーザーが B を選択して F にドラッグしようとした場合、どうすればそれを防ぐことができますか?

私はロジックを探しています。B から F は問題ありませんが、F から B は問題ありません。

4

11 に答える 11

4

現在の DB スキーマでは、複数の選択ステートメントのオプションのみが表示されます。ルートまたは最後の子に到達するまで、ツリーを上または下にチェックする必要があります(nietonfirsの回答のように)。

私自身、フル パスを含む 4 番目の列をテーブルに追加します。

id   name   childOf   pathToFolder
----------------------------------
1      A        0      ,1,
2      B        1      ,1,2,
3      C        0      ,1,3,
4      D        3      ,1,3,4,
5      E        2      ,1,2,5,
6      F        5      ,1,2,5,6,

この新しいデータを使用するには、いくつかの方法があります。1 つの方法は、誰かが B を移動したい場合、有効な移動先のリストを取得することです。SELECT id FROM folders WHERE pathToFolder NOT LIKE ',1,2,%'

この種の操作は最速ではありませんが、非常に便利です。

于 2013-10-16T16:55:58.947 に答える
1

ターゲットと宛先の両方(またはデータオブジェクト全体など)のIDを取得し、ターゲットが宛先パスにあるかどうかを確認するメソッドがあると思います。そうである場合、メソッドは false を返すか例外をスローし、そうでない場合は true を返します。このメソッドは、制御構造としてコード フローをコピーするディレクトリに導入できます。

個人的には、階層データ構造の場合は、ネストされた setとして実装します。ネストされたセットのセットアップと修正は面倒ですが、ノード間の関係をチェックし、サブツリー全体を取得するには非常に便利です。

これは、私のアイデアの部分的でやや単純な実装を使用した PHPUnit テストです。

<?php

ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(-1);

require 'vendor/autoload.php';

class ParentingSucks
{

    public $data = array();

    public function isAllowed($targetId, $destId)
    {
        $target = $this->getById($targetId);
        $dest = $this->getById($destId);
        $parent = $this->getById($dest['childOf']);

        $isAllowed = true;
        while ($parent) {
            if ($parent['id'] == $targetId) {
                $isAllowed = false;
                break;
            }

            $parent = $this->getById($parent['childOf']);
        }

        return $isAllowed;
    }

    public function getById($id)
    {
        if (isset($this->data[$id])) {
            return $this->data[$id];
        }
        return array();
     }
}

class HowIMetYourParentDir extends PHPUnit_Framework_TestCase
{

    /**
     * @test
     * @dataProvider generate
     */
    public function droppingOnParentNotAllowed($data, $target, $dest, $outcome)
    {

        $stub = $this->getMock('ParentingSucks', null);
        $stub->data = $data;

        $result = $stub->isAllowed($target, $dest);

        $this->assertEquals($result, $outcome, 'Oh no!');
    }

    public function generate()
    {
        $fakeData = array(
            1 => array('id' => 1, 'name' => 'A', 'childOf' => 0),
            2 => array('id' => 2, 'name' => 'B', 'childOf' => 1),
            3 => array('id' => 3, 'name' => 'C', 'childOf' => 0),
            4 => array('id' => 4, 'name' => 'D', 'childOf' => 3),
            5 => array('id' => 5, 'name' => 'E', 'childOf' => 2),
            6 => array('id' => 6, 'name' => 'F', 'childOf' => 5),
        );
        return array(
            array(
                $fakeData,
                2, // target
                6, // dest
                false, // outcome
            ),
            array(
                $fakeData,
                4,
                2,
                true,
            ),
            array(
                $fakeData,
                4,
                2,
                true,
            ),
            array(
                $fakeData,
                3,
                4,
                false,
            ),
        );
    }
}              false, // outcome
            ),
            array(
                $fakeData,
                4,
                2,
                true,
            ),
            array(
                $fakeData,
                4,
                2,
                true,
            ),
            array(
                $fakeData,
                3,
                4,
                false,
            ),
        );
    }
}

変数/関数/クラスの名前はおそらくドメイン モデルに適合しないため、気にしないでください。

于 2013-10-16T16:32:56.330 に答える
1

ロジックは非常に単純です。

と が の祖先でない場合に限り、フォルダをターゲットフォルダfにドラッグできます。tf<>tft

質問にはのタグが付けられており、RDBMSが指定されていないため、フォルダーが次のようなphp配列にあると仮定します。

$namespace=array(
  1=>array('name'=>'A','parent'=>0),
  2=>array('name'=>'B','parent'=>1),
  3=>array('name'=>'C','parent'=>0),
  4=>array('name'=>'D','parent'=>3),
  5=>array('name'=>'E','parent'=>2),
  6=>array('name'=>'F','parent'=>5),
  );

$fが の祖先であるかどうかを判断するには、(1) が見つかるか、(2)ルート (名前空間に複数のルートがあるため、ルートではない)に到達するまで、ツリーを上方向にたどる$t必要があります。したがって、次の関数を検討してください。$t$f

function is_ancestor($f,$t)
  {
  global $namespace;
  $are_equal=($f==$t);
  $t_parent=$namespace[$t]['parent'];
  $is_root=!isset($namespace[$t_parent]);
  return $are_equal || (!$is_root && is_ancestor($f,$t_parent));
  }

とてもわかりやすいと思います。ただし、2 つの点があります。(1) どうやら、パラメーターはフォルダーidsであり、(2) 名前にもかかわらず、関数$fは が の祖先であるかどうかだけ$tでなく、それらが等しいかどうかもチェックします。

この php fiddleで、コンセプト全体を実際に見ることができます。

于 2013-10-23T07:10:47.710 に答える
0

2 つの関数を作成し、各 ID のすべての最上位の親を取得します。つまり、B から A まで、同様に F から最上位の親 F から C まで、ID を 2 つの異なる配列に格納します。次に、2 つの配列に共通するものがあるかどうかを確認します。かどうか.If common cn drag else can't dragged

于 2013-10-23T13:25:25.287 に答える
0

この質問は、私の語学クラスでのことを思い出させます。そこで私は次のような解決策を考え出しました: 架空の方法でツリーを構築させてください。ルート (id:0) を R、最後を -1 とします。

R:AC
A:B
B:E
E:F
F:-1
C:D
D:-1

しかし、物事を速くしたいだけでは十分ではありません。これらも追加しましょう:

R:BC
R:EC
R:FC

R:BD
R:ED
R:FD

あなたのために物事を整理させてください:

R:AC
R:AD *I added this one
R:BC
R:EC
R:FC
R:BD
R:ED
R:FD
R:A * this one too
R:C * this one too
A:B
B:E
E:F
C:D
F:-1
D:-1

これで十分です。だから、あなたは言った

たとえば、D から B は OK、D から E は OK、B から F は独自のツリーにドラッグするので OK ではありませんが、F から B はツリーを上にドラッグするので OK です。

ほら、D to Bでいいの?右から左にチェックする必要があります。Dはどこ?そうそう、あなたが.. R:BD! じゃあ、一緒ならいいの?はい、大丈夫です。DからE?赤!はい、こちらも大丈夫です。BからF?一緒にBF見よう…いやは?では右側に B … A:B があるので AR:A をチェックしてみましょう!ブーム!B

これは、物事を別の方法で見るための提案にすぎません。それはさまざまな見方によって行うことができます。しかし、このような言語文法を使用すると役立つと本当に思います。オンエアで作成することも、場合によってはマップファイルとして作成することもできます。しかし、多くの状況での複雑さは本当に低いです。最善の解決策を見つけて頑張ってください!

于 2013-10-21T23:04:03.690 に答える
0

私はあなたの問題を理解していません。アルゴリズムは実にシンプルです。

PHP が呼び出されるたびに、最初にフォルダーがターゲット フォルダーのサブ フォルダーではないかどうかを確認します。あなたの場合、これはうまくいきません。すべてのオペレーティング システムがファイル パスを使用するため、数値 ID を使用してフォルダーやファイルを保存しないでください。

ちょうどこのような:

url                    type     description
-------------------------------------------------
ROOT/folder            2        Image folder...
ROOT/hallo             1        Hallo directory..
ROOT/hallo/subfolder   1        I am a sub dir..

これで必要な列は 1 つだけになりましたが、それは全文索引になります。フォルダーが独自のサブフォルダーの親ではないかどうかを確認する場合は、単に URL を確認します。

ROOT/hallo私があなたに描くときのように、ROOT/hallo/subfolderこれを行うだけです:

ROOT/ハロー = 10 文字

ROOT/ハロー/サブフォルダー = 20 文字

<?php

    $selected_folder = 'ROOT/hallo';
    $subject_folder = 'ROOT/hallo/subfolder';

    $length = strlen($selected_folder);
    if($selected_folder != substr($subject_folder,0,$length)){
         echo 'go';
    }
    else{
        echo 'Can not relocate folder to its own subfolder';
    }

?>
于 2013-10-22T07:08:03.380 に答える
0

ルートフォルダーに到達するまで、親を確認するだけですか? 疑似コードで

// targetFolder is the target folder where the folder is going to be moved
// while sourceFolder is the folder that's moved.
parents = targetFolder.getParents();
if (parents.contains(sourceFolder)) {
    // don't allow the operation
}
于 2013-10-08T09:13:42.403 に答える