我有一个使用CakePHP 2.x和jstree 3.2.1的应用程序。我试图弄清楚在使用CakePHP将节点写入数据库时如何指定节点的位置。该职位本身来自jstree ......
当我使用jstree拖放项目时,请求URL会给我:
id
- 正在拖动的节点的ID。parent_id
- 已删除节点的(父)ID。position
- 这是一个从0开始的整数,表示id
下parent_id
被删除的位置。例如,position
2
表示它应该出现在第3个位置(第3个,而不是第2个,因为它们从0开始)。 CakePHP中的方法Tree Behaviour允许您上下移动树中的节点。这些方法分别称为moveUp()
和moveDown()
。
我不明白如何使用jstree提供的数据与Cake的树行为,以便您可以正确更新/保存位置。 < / p>
将position
传递给moveUp()
或moveDown()
会产生错误的结果。为什么呢?
position = 2
并且您正在通过CakePHP调用moveUp(2)
的列表中移动第10个项目意味着它将进入第8个位置,而不是按预期进入第2个位置。同样,moveDown(2)
会将其移至第12位,这不是理想的结果。 Cake为其提供的架构树行为没有&#34;位置&#34;领域。而是使用lft
和rght
字段。架构有:
id
- 每个树节点的ID(自动增量)parent_id
- 节点的父ID。 NULL
如果是最高级别(没有父级)。lft
,rght
- 用于MPTT逻辑。 Cake会自动生成这些值。它们可用于使用ORDER BY lft ASC
确定订单。但它们与jstree提供的position
值不同,并且每行都是唯一的 name
- 节点的文本名称。例如,请考虑以下树:
id
= 149
)
id
= 150
,parent_id
= 149
)id
= 153
,parent_id
= 149
)id
= 154
,parent_id
= 149
)id
= 155
,parent_id
= 149
)id
= 156
,parent_id
= 149
)在数据库Cake中存储如下:
如果我要使用jstree来拖放&#34; 2&#34;所以它出现在&#34; 3&#34;和&#34; 4&#34;它会发出一个包含以下GET变量的请求:
id
= 153
。这是&#34; 2&#34;
parent_id
= 149
。这是&#34; D&#34;的ID这是&#34; 2&#34;的父节点。
position
= 2
。这意味着第3个位置(第3个位置,因为位置从0开始)。
但我无法从此数据中重新生成lft
和rght
值? moveUp()
/ moveDown()
在这里没有帮助,因为position
无法以一种可以使其发挥作用的方式传递。
树应按以下顺序排列。 id
和parent_id
不应更改,但lft
和rght
必须更改,因为&#34; D&#34;已被有效重新订购:
任何人都可以帮忙吗?
答案 0 :(得分:1)
我从未使用过jsTree,但如果它为您提供了新的父ID和排序位置,那么您应该可以使用保存新父级的组合:
$Model->save(array('parent_id' => $parentId));
之后获得其子列表,其中包括新孩子:
$children = $Model->children($parentId, true, array('id'));
并使用排序位置确定移动修改后的子项的增量:
$childIds = Hash::extract($children, '{n}.Model.id');
$positionMap = array_flip($childIds);
$currentPosition = $positionMap[$nodeId];
$delta = (int)$position - $currentPosition;
if ($delta !== 0) {
if ($delta < 0) {
$Model->moveUp($nodeId, abs($delta));
} else {
$Model->moveDown($nodeId, abs($delta));
}
}
这只是一个粗略的例子,应该说明这是如何工作的想法,它假设$parentId
是新父的ID,$nodeId
是要移动的行的ID ,和$position
孩子被移动到的(零基础)位置。您也必须考虑其他情况,例如父母ID没有变化,即只有排序位置发生变化,这应该都是在交易中完成的!
这是一个基于Cookbook示例的完整代码段,它会将Gwendolyn
节点移动到Work
节点中的第二个位置:
$nodeId = 8;
$parentId = 9;
$position = 1;
$dataSource = $this->Category->getDataSource();
$dataSource->begin();
$this->Category->id = $nodeId;
if (!$this->Category->save(array('parent_id' => $parentId))) {
$dataSource->rollback();
} else {
$children = $this->Category->children($parentId, true, array('id'));
$childIds = Hash::extract($children, '{n}.Category.id');
$positionMap = array_flip($childIds);
$result = true;
if (isset($positionMap[$nodeId])) {
$currentPosition = $positionMap[$nodeId];
$delta = (int)$position - $currentPosition;
if ($delta !== 0) {
if ($delta < 0) {
$result = $this->Category->moveUp($nodeId, abs($delta));
} else {
$result = $this->Category->moveDown($nodeId, abs($delta));
}
}
}
if ($result) {
$dataSource->commit();
} else {
$dataSource->rollback();
}
}