Zend Framework hierarchical Zend_Db_Table extension

After a few hours looking for a good implementation of recursive data with Zend Framework, I came across Hector Virgen's table abstraction for nested recursive tables, which uses the efficiency of the Modified Preorder Tree Traversal method that retrieves descendents and ancestors faster that with the old parent_id reference. In fact parent_id is not needed any more but in the example below we will keep the parent_id implementation. My aim here is to implement a draggable tree with data from this Zend_DB_Table abstraction. Setting up ext js with Zend Framework is not that hard, especially when many tutorials have been posted around for extjs tree with other frameworks such as Cake PHP .

The Hierarchical zend_db_table extension is the first part of the problem : we have simplified Virgen's db_table extension to let it work with just parent_id. Here you will find basic functions that allow you to count children of a particular record and list them as rowset rows.

Usage :

include("Hierarchical_Db_Table.php");
class Theme2 extends Hierarchical_Db_Table  {    protected  $_parentKey = "parent_id";}
$theme=new Theme2;
if ($node=="0" || $node=="") $thRowSet = $theme->fetchTop();
else $thRowSet=$theme->fetchChildren($node);

File : Hierarchical_Db_Table.php

info();
		return $info[primary][1];
	}
public function fetchTop(  Zend_Db_Select $select = null)
	{
		if (null === $select) {
            $select = $this->select();
        }
        
        $select->where($this->_parentKey . ' is NULL' );     
		return $this->fetchAll($select);
	}
public function CountChildren($row, Zend_Db_Select $select = null)
	{
		 if ($row instanceof Zend_Db_Table_Row_Abstract) {
            $_row = $row;
        } else if (is_string($row) OR is_numeric($row)) {
            $_row = $this->find($row)->current();
            if (null === $_row) {
                require_once 'Zend/Db/Exception.php';
                throw new Zend_Db_Exception("Cannot find row '" . $this->_traversal['column'] . "' = {$row}");
            }
        } else {
            require_once 'Zend/Db/Exception.php';
            throw new Zend_Db_Exception("Expecting instance of Zend_Db_Table_Row_Abstract, a string, or numeric");
        }
		
		 if (null === $select) {
            $select = $this->select();
        }
		 $parent_id = $_row->{$this->primaryKey()};
        $select->where($this->_parentKey . ' = ?', (int) $parent_id)  ;
		
		$select->from($this, array("count(" . $this->primaryKey() . ") as c"));
		$row =		$this->fetchAll($select)->current();
		//print_r($select->toArray());
		//Zend_Debug::dump( $this->_parentKey .  $parent_id);
		return $row->c;
	}
public function fetchChildren($row, Zend_Db_Select $select = null)
	{
		 if ($row instanceof Zend_Db_Table_Row_Abstract) {
            $_row = $row;
        } else if (is_string($row) OR is_numeric($row)) {
             $_row = $this->find($row)->current();
            if (null === $_row) {
                require_once 'Zend/Db/Exception.php';
                throw new Zend_Db_Exception("Cannot find row '" . $this->primaryKey(). "' = {$row}");
            }
        } else {
            require_once 'Zend/Db/Exception.php';
            throw new Zend_Db_Exception("Expecting instance of Zend_Db_Table_Row_Abstract, a string, or numeric");
        }
		
		 if (null === $select) {
            $select = $this->select();
        }
	 
         $parent_id = $_row->{$this->primaryKey()};
		//print_r($_row);
        $select->where($this->_parentKey . ' = ?', (int) $parent_id)        ;
        return $this->fetchAll($select);
	}
}
1 reply

Leave a Reply

Want to join the discussion?
Feel free to contribute!

Leave a Reply

Your email address will not be published. Required fields are marked *