2011-07-22 16 views
0

私は、より多くのルートを持つテーブルセットを設定しようとしています。テーブルのネストされたセットにDoctrine 1.2

私が読んでいるExcelファイルからそれらを保存するためのデータ。

私はこのスクリプトを書く:

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"; 

} 

と私の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; 
    } 
} 

私の教義スキーマ:

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) 

問題は、私は与えられたノードをチェックするために行くときということです次のようなクエリを実行すると、州を調べます:

SELECT * FROM locations WHERE lft >= x AND rgt <= y 

私が見つけることが期待される都市は見つかりませんが、私ははるかに見つけることができます。

読み取りファイルは完璧に動作します。私は印刷し、すべての出力を読んで、正しい。 lftとrgtの値が間違っていると思います。 あなたはprensaではないドキュメントにいくつかのバグを発見したことは知っていますか?

答えて

0

お客様の定義にhasManyRootsが設定されています。つまり、ネストされたセットテーブルには複数のツリーが含まれています。各ツリー内のlftrgtは他のツリーとは独立して構築されているため、SELECT * FROM locations WHERE lft >= x AND rgt <= yでクエリを実行すると、複数のツリーからノードが取得されます。

あなたはそれを修正する2つの方法があります:迅速かつ正しい。

迅速な1

は:

すべてのレコードがroot_id持つ列(rootColumnName属性にセットし、それはまた、デフォルト値です)。この列には、ツリーのルートノードのidが含まれています。だから、あなたが希望するノードのroot_idを知っていると

SELECT * FROM locations WHERE lft >= x AND rgt <= y and root_id = rid 

ようにそれを使用するために右のいずれかがある場合:

を直接DBを照会しないでください。 (例えばDQLで)及びgetChildren又はgetDescendantsを使用してそれを横切るよりオブジェクトとしてDBから所望のレコードをフェッチ:

// Get the node into $provincevar 
$all_cities_in_province = $province->getDescendants(); 

より詳細な説明についてNestedSet documentationを参照してください。

そして少し注記:偶然の一致かもしれないが、キャッシュまたは何か他のものの不在が、Doctrineはimmidiately NestedSetノード操作関数によって行われた変更(例えばcreateRootdeleteinsertAsLastChildOfなど)をフラッシュするように見えます。しかし、これは開発環境のある単一のマシンでの私の観察です。

関連する問題