简体   繁体   English

填充表嵌套集 Doctrine 1.2

[英]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.在每棵树中, lftrgt都独立于其他树构建,因此使用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 ),然后使用getChildrengetDescendants遍历它:

// 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节点操作函数(例如createRootdeleteinsertAsLastChildOf等)所做的更改。 But that is my observation made on single machine with development environment.但这是我在具有开发环境的单机上所做的观察。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM