[英]Populate table nested set Doctrine 1.2
I'm trying to populate a table set with more root Locations nested three levels: Region, Province and City.我正在尝试使用嵌套三个级别的更多根位置填充表集:地区、省和市。
the data to save them from an excel file I'm reading.从我正在阅读的 excel 文件中保存它们的数据。
i write this script:我写这个脚本:
function importLocations()
{
$objPHPExcel = PHPExcel_IOFactory::load("./data/elenco_comuni_italiani_30_giugno_2011.xls");
$locationTable = LocationTable::getInstance();
/* @var $tree Doctrine_Tree_NestedSet */
$tree = $locationTable->getTree();
$startRow = 2;
$indexRegion = 0;
$indexProvince = 2;
$indexCity = 1;
$objPHPExcel->setActiveSheetIndex($indexRegion);
$objWorksheetRegion = $objPHPExcel->getActiveSheet();
$highestRowRegion = $objWorksheetRegion->getHighestRow();
$highestColumnRegion = $objWorksheetRegion->getHighestColumn();
$highestColumnIndex = PHPExcel_Cell::columnIndexFromString($highestColumnRegion);
for ($rowRegion = $startRow; $rowRegion <= $highestRowRegion; ++$rowRegion) {
$region_name = $objWorksheetRegion->getCellByColumnAndRow(0, $rowRegion)->getValue();
$region_id = $objWorksheetRegion->getCellByColumnAndRow(1, $rowRegion)->getValue();
// create a new root in the tree
$tree->createRoot($nodeRegion = $locationTable->createNode($region_name));
echo "\n\Process to Region: $region_name \n";
//province
$objPHPExcel->setActiveSheetIndex($indexProvince);
$objWorksheetProvince = $objPHPExcel->getActiveSheet();
$highestRowProvince = $objWorksheetProvince->getHighestRow();
$highestColumnProvince = $objWorksheetProvince->getHighestColumn();
$highestColumnIndex = PHPExcel_Cell::columnIndexFromString($highestColumnProvince);
for ($rowProvince = $startRow; $rowProvince <= $highestRowProvince; ++$rowProvince) {
$province_name = $objWorksheetProvince->getCellByColumnAndRow(0, $rowProvince)->getValue();
$province_code = $objWorksheetProvince->getCellByColumnAndRow(1, $rowProvince)->getValue();
$province_region_id = $objWorksheetProvince->getCellByColumnAndRow(2, $rowProvince)->getValue();
$province_id = $objWorksheetProvince->getCellByColumnAndRow(3, $rowProvince)->getValue();
if ($province_region_id == $region_id) {
//create province node and append it to the region
$nodeProvince = $locationTable->createNode($province_name, $province_code);
$locationTable->appendNode($nodeProvince, $nodeRegion);
echo "Process to Province: $province_name \n";
//city
$objPHPExcel->setActiveSheetIndex($indexCity);
$objWorksheetCity = $objPHPExcel->getActiveSheet();
$highestRowCity = $objWorksheetCity->getHighestRow();
$highestColumnCity = $objWorksheetCity->getHighestColumn();
$highestColumnIndex = PHPExcel_Cell::columnIndexFromString($highestColumnCity);
for ($rowCity = $startRow; $rowCity <= $highestRowCity; ++$rowCity) {
$city_name = $objWorksheetCity->getCellByColumnAndRow(0, $rowCity)->getValue();
$city_province_id = $objWorksheetCity->getCellByColumnAndRow(1, $rowCity)->getValue();
$city_region_id = $objWorksheetCity->getCellByColumnAndRow(2, $rowCity)->getValue();
if ($city_region_id == $province_region_id && $city_province_id == $province_id) {
//create province node and append it to the region
$nodeCity = $locationTable->createNode($city_name);
$locationTable->appendNode($nodeCity, $nodeProvince);
echo "Process to City: $city_name \n";
}
}
}
}
}
echo "Locations Salvate con Successo! \n\n\n";
}
and my LocationTable:和我的位置表:
/**
* LocationTable
*
* This class has been auto-generated by the Doctrine ORM Framework
*/
class LocationTable extends Doctrine_Table
{
const LEVEL_REGION = '0';
const LEVEL_PROVINCE = '1';
const LEVEL_CITY = '2';
/**
* Returns an instance of this class.
*
* @return object LocationTable
*/
public static function getInstance()
{
return Doctrine_Core::getTable('Location');
}
/**
* Developer MUST CALL $parent->refresh() before insert a new node, otherwise
* following insertions are wrong
*
* @param Location $son
* @param Location $parent
* @link http://trac.doctrine-project.org/ticket/928
*/
public function appendNode(Location $son, Location $parent)
{
// internally calls save both on parent and son
$son->getNode()->insertAsLastChildOf($parent);
// load new parent lft and rgt values
$parent->refresh();
}
/**
* Build a tree node, save it and return it
*
* @param string $label
* @param string $code
*
* @return Location
*/
public function createNode($label, $code = null)
{
$node = $this->create(array('name' => $label, 'code' => $code));
$node->save();
return $node;
}
}
my doctrine schema:我的 doctrine 架构:
Location:
tableName: locations
actAs:
NestedSet:
hasManyRoots: true
rootColumnName: root_id
columns:
id:
type: integer(4)
primary: true
autoincrement: true
name:
type: string(255)
notnull: true
code:
type: string(2)
the problem is that when I go to check a given node, we examine a province, if I perform a query like:问题是当我 go 检查给定节点时,我们检查一个省,如果我执行如下查询:
SELECT * FROM locations WHERE lft >= x AND rgt <= y
I can not find the city that I expect to find, but I find much more.我找不到我期望找到的城市,但我找到了更多。
the scritp that reads excel file it works perfectly.读取 excel 文件的脚本运行良好。 I printed and read all the output and correct.
我打印并阅读了所有 output 并正确。 I think there is something wrong in the lft and rgt values saved.
我认为保存的 lft 和 rgt 值有问题。 You know you have found a few bugs in the documentation that is not prensa?
您知道您在文档中发现了一些不是 prensa 的错误吗?
You have hasManyRoots
set in your definition.您在定义中设置了
hasManyRoots
。 That means, that your nested set table contains several trees.这意味着,您的嵌套集表包含几棵树。 in each tree
lft
and rgt
are built independent of other trees, so querying with SELECT * FROM locations WHERE lft >= x AND rgt <= y
retrieves nodes from several trees.在每棵树中,
lft
和rgt
都独立于其他树构建,因此使用SELECT * FROM locations WHERE lft >= x AND rgt <= y
从几棵树中检索节点。
You have two options to fix it: quick and right.您有两种选择来解决它:快速和正确。
The quick one:快速的一个:
Every record has a root_id
(set in rootColumnName
attribute, it is also the default value) column.每条记录都有一个
root_id
(在rootColumnName
属性中设置,也是默认值)列。 This column contains the id
of the tree's root node.此列包含树的根节点的
id
。 So, if you have to know the root_id
of your desired node and use it like因此,如果您必须知道所需节点的
root_id
并像这样使用它
SELECT * FROM locations WHERE lft >= x AND rgt <= y and root_id = rid
The right one:正确的那一个:
Don't query the db directly.不要直接查询数据库。 Fetch the desired record from the DB as object (eg with
DQL
) and than traverse it using getChildren
or getDescendants
:从数据库中获取所需的记录为 object (例如使用
DQL
),然后使用getChildren
或getDescendants
遍历它:
// Get the node into $provincevar
$all_cities_in_province = $province->getDescendants();
See NestedSet documentation for more detailed explanation.有关更详细的说明,请参阅NestedSet 文档。
And a little note: that might be a coincidence, absence of caching or something else, but it looks like Doctrine immidiately flushes changes made by NestedSet
node manipulation functions (eg createRoot
, delete
, insertAsLastChildOf
etc.).还有一点注意:这可能是巧合,没有缓存或其他原因,但看起来 Doctrine 立即刷新了
NestedSet
节点操作函数(例如createRoot
、 delete
、 insertAsLastChildOf
等)所做的更改。 But that is my observation made on single machine with development environment.但这是我在具有开发环境的单机上所做的观察。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.