1

テーブルに次のエントリがあります。

id  name          unit_id   lft rgt level
------------------------------------------
1   Sports        01        1   30  0
2   Cricket       02        2   3   1
3   Hocky         03        10  13  1
4   Tennies       04        11  12  2
5   Baseball      05        14  15  1
6   Soccer        06        16  25  1
7   Carrom        07        17  22  2

上記のレコードは手動で挿入されます。ここで、親子関係<ul><li>タグに表示するために、codeigniterにレコードを動的に挿入します。私はこの記事を参照しています:

http://www.sitepoint.com/hierarchical-data-database-3/

以下のコードを参考にして行いました。

$description = $_GET['description'];
$name = $_GET['name'];
$unit_id = $_GET['unit_id'];

$parent_level = (int) $_GET['level'];
$level = (int) $_GET['level'] + 1;

$sql0 = "Select `lft`, `rgt` from tablename
Where `level` = $parent_level";

$result = $this->db->query($sql0);
$records = $result->result_array();

$lft = $records[0]['lft'];
$rgt = $records[0]['rgt'];

$sql1 = "UPDATE tablename SET rgt = rgt+2 WHERE rgt >  $rgt ";
$this->db->query($sql1);
$sql2 = "UPDATE tablename SET lft = lft+2 WHERE lft > $lft ";
$this->db->query($sql2);
$sql3 = "INSERT INTO tablename (`id`,`name`,`unit_id`,`description`, `lft`, `rgt`, `level`)        
values (NULL, '$name', '$unit_id','$description', '$lft', '$rgt', '$level')";
echo $this->db->query($sql3);

しかし、このコードは正しく機能しておらず、親子関係を維持していません。私はいくつかの間違った計算がここにあると思いますが、それで何が間違っているのかを知ることができません。

私は助けが必要です。ありがとうございます。

4

3 に答える 3

1

コードを少し更新しましょうが、最初にいくつかのメモがあります。

1-情報は整数であるため、(int)を追加すると、SQLインジェクションを回避するのに役立ちます

2-最後のクエリで更新と挿入構文を混在させました:)(ianはこれに注意しました)

3-すべての変数(level、lft、rgt、level、unit_id、name)に値があることを確認します。クエリの前に、それらをエコーし​​て確認できます。

4-通常、mysql関数は、マルチクエリソリューションを使用していない限り、一度に1つのクエリしか処理できません。そのため、$ sql1、$ sql2、および$ sql3という名前を付けました。必要なのは、それらを次々に実行することだけです。

5-文字列値は引用符(')で囲む必要があり、mysqlは整数に対してもこれを受け入れます

6- mysqlキーワードとの衝突を克服するために、フィールドにはバッククォート( `)を付ける方がよい

7- mysqlのエラー出力を確認します。使用しているAPIはわかりませんが、デフォルトのmysqlはmysql_errorを使用します。

8- mysql-real-escape-stringまたはセットアップに応じた同等の関数を使用して挿入する前に、名前とunit_id(varcharのようです)の値をエスケープしてください。これもSQLインジェクションから保護します。

$level = (int) $_GET['level'] + 1;
$lft   = (int) $_GET['lft'] + 1;
$rgt   = (int) $_GET['rgt'] + 1;

$sql1  = "UPDATE tablename SET rgt = rgt+2 WHERE rgt >  $rgt ";
//in the below line, it was $rgt, but I guess you meant $lft
$sql2  = "UPDATE tablename SET lft = lft+2 WHERE lft > $lft ";  
$sql3  = "INSERT INTO tablename (`id`,`name`,`unit_id`, `lft`, `rgt`, `level`)
    values (NULL, '$name', '$unit_id', '$lft', '$rgt', '$level')";

今、上記のコードショーはこのようなものを生成します

id  name        lft rgt level
------------------------------------
1   company     1   22  0
2   qa          3   24  1
3   tester      5   26  1
4   developer   7   28  1

会社をベースとして使用する場合は、レベル0に1つだけ追加する必要があります。これは、すでに実行されています。

次に、メインレベル(この場合はレベル0)のlftとrgtに、最後の項目ではなく追加する必要があります。これは、コメントから明らかです。

あなたが持っているべき結果は次のとおりです

id  name        lft rgt level
------------------------------------
1   company     1   22  0
2   qa          3   24  1
3   tester      3   24  1
4   developer   3   24  1

ご覧のとおり、レベルを追加する場合、lftとrgtは2を追加するだけですが、同じレベルの場合は常に同じである必要があります。この方法を使用すると、同じレベルが一緒に表示されます。

私が言ったことを反映するようにコードを更新した後、それは次のようになるはずです

$description = $_GET['description'];
$name = $_GET['name'];
$unit_id = $_GET['unit_id'];

$parent_level = (int) $_GET['level'];
$level = (int) $_GET['level'] + 1;

//check lft and rgt for parent 
$sql = "Select `lft`, `rgt` from tablename
    Where `level` = $parent_level";
$result = $this->db->query($sql);
$records = $result->result_array();

$lft = $records[0]['lft'] + 2;
$rgt = $records[0]['rgt'] + 2;

//check in case there is levels after the one we will add
$sql = "count(*) from tablename
    Where `level` >= $level";
$result = $this->db->query($sql);
$records = $result->row_array();
$count = $records[0];
if ( $count > 0 ) { //we have to move child nodes one step
    $sql = "UPDATE tablename SET rgt = rgt+2, lft = lft + 2, level = level + 1 
        WHERE level >= $level";
    $this->db->query($sql);
}
$sql = "INSERT INTO tablename (`id`,`name`,`unit_id`,`description`, `lft`, `rgt`, `level`)        
    values (NULL, '$name', '$unit_id','$description', '$lft', '$rgt', '$level')";
echo $this->db->query($sql);

これがそれを修正することを願っています:)

于 2012-07-31T22:01:14.073 に答える
0

OKネストされたセットへの要素の挿入は少し複雑ですが、これは役立つはずです...

あなたは次のようなものをヒットします:

/insert.php?name=newsport&level=2&lft=11&rgt=12;

あなたは、私たちが最初にこれのためにいくらかの余地を作らなければならないことを正しく識別します。

これは、lft>=11およびrgt+2の場合はlft+2を増やすことで達成できます。ここで、rgt>=10です。

説明:

lft>=11は間違いなく上に移動する必要があります。rgt> = 10 rgtを持つすべての要素は、挿入するlftより1以上小さい。

これは1つのクエリで実行できます。

UPDATE tablename
SET lft = CASE
          WHEN lft>= $_GET['lft'] THEN lft+2
          ELSE lft END,
    rgt = rgt+2
WHERE rgt >= ($_GET['lft'] - 1);

次に、新しい要素を挿入します。

INSERT INTO tablename
(`id`, `name`, `unit_id`, lft, rgt, level )
VALUES
(NULL, $_GET['name'], UNIT_ID, $_GET['lft'], $_GET['rgt'] ); 

UNIT_IDをどのように生成するかわからないため、自分で生成する必要があります。これは、別の$_GET変数である可能性があります。

挿入では、挿入ではなく更新構文を使用しています。

その後、更新または挿入時にデータベースからエラーのエコーを開始する必要があります。

于 2012-07-31T11:53:39.217 に答える
0

これを試して:

$name = $_GET['name'];
$unit_id = $_GET['unit_id'];
$rgt = $_GET['rgt'];
$lft = $_GET['lft'];
$level = $_GET['level'] + 1;
$right = $rgt + 1;

$sql1 = "UPDATE xp_subunit SET lft = lft+2 WHERE lft >= $rgt ;";
$this->db->query($sql1);
$sql2 = "UPDATE xp_subunit SET rgt = rgt+2 WHERE rgt >= $rgt ;";
$this->db->query($sql2);
$sql3 = "INSERT INTO xp_subunit (`id`,`name`,`unit_id`,`lft`, `rgt`,   
`level`) values (NULL, '$name', '$unit_id',$rgt, $right, '$level');";
$this->db->query($sql3);
于 2012-08-07T10:09:32.113 に答える