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>现在我想在 codeigniter 中动态插入记录,以便在<li>标签中显示父子关系。我指的是这篇文章:

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-确保每个变量(级别、lft、rgt、级别、unit_id 和名称)都有一个值,您可以在查询前简单地回显它们以进行检查。

4-通常mysql函数一次只能处理一个查询,除非你使用多查询解决方案,这就是我命名$sql1、$sql2和$sql3的原因,你所要做的就是一个接一个地执行它们

5-字符串值应该有引号('),mysql甚至接受这个整数

6- 字段最好有反引号 (`) 以克服与 mysql 关键字的冲突

7-检查mysql的错误输出,不确定你使用的是什么api,但默认mysql使用mysql_error

8- 确保在插入之前根据您的设置使用mysql-real-escape-string或等效函数转义name 和 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

如果您想使用公司作为基础,您应该只将 1 添加到 0 级,我们已经这样做了

然后我们必须添加到主级别(在我们的例子中是级别 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

尝试这个:

$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 回答
0

OK 在嵌套集合中插入元素有点复杂,但这应该有助于...

你遇到了类似的事情:

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

您正确地指出我们必须首先为此腾出一些空间。

我们通过为 lft >= 11 和 rgt+2 (其中 rgt >= 10)增加 lft+2 来实现这一点;

解释:

lft >= 11 肯定要向上移动。rgt >= 10 具有 rgt 的所有元素大于或等于 1,小于您要插入的 lft。

我们可以通过一个查询来做到这一点。

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 回答