Набор классов для построения деревьев

10.06.2016

Рекурсивное построение дерева на основе элементов полученных из базы данных.

Библиотеку для соединения с ДБ можно выбрать на свое усмотрение.

Пример вывода

pic1

Код для подключения (Дэмо)

_init_.php (Download)

 <?

  /**
  * Базовый класс для дерева
  * 
  */
  class soTree
  {
    /**
	* Демонстрационный метод, для создания дерева.
	* Возвращает дерево в виде UL>LI списка
	* 
	* @return string
	*/
    static function demoUl()
    {
      require_once('models/tree.php');
      $oModel = new soModelTree();

      require_once('views/ul.php');
      $oView = new soViewTreeUL();

      // Предаем на вход ID активного элемента. 
      // В дереве будет подсветка пути до выбранного элемента
      $aItems = $oModel->getItems(['id_selected' => 10]);
      return $oView->render($aItems);
	}


    /**
	* Демонстрационный метод, для создания дерева.
	* Возвращает дерево в виде DIV списка
	* 
	* @return string
	*/
    static function demoDiv()
    {
      require_once('models/tree.php');
      $oModel = new soModelTree();

      require_once('views/div.php');
      $oView = new soViewTreeDiv();

      // Предаем на вход ID активного элемента. 
      // В дереве будет подсветка пути до выбранного элемента
      $aItems = $oModel->getItems(['id_selected' => 10]);
      return $oView->render($aItems);
	}

  }

Моледь

tree.php (Download)

 <?

  /**
  * Модель. Класс для получения данных о дереве из БД
  */
  class soModelTree
  {
    /**
	* 
	* @var array - массав "для пути" от корня до выбранного элемента, со всеми id 
	* 
	*/
    protected $_aActivePath = array();

    /**
	* 
	* @var object - объект для взаимодействия с ДБ
	* 
	*/
    protected $_oDB = NULL;


    #-------------------------------------------------------#

    /**
	* Construct
	*/
    function __construct() 
    {
      // !!! Т.к. Модуль может использоватся для разных целей, то тут нужно писать индивидуально.

      //- $this->_oDB = soLibKeeper::factory('DBO');

      global $oDB;
      $this->_oDB = $oDB;
    }

    /**
    * Метод для формирования "пути" (списка всех ID от корян до выбранного элемента)
	* 
	* @param int $id
	* 
	* @return $this
	*/
    protected function _initActivePath($id)
    {
      $this->_aActivePath[] = $id;

      $sSql = 'SELECT * FROM `tree` WHERE published=1 AND id='.$id;
      $oRow = $this->_getRow($sSql);
      if($oRow->id_parent)
      {
        $this->_initActivePath($oRow->id_parent);
      }
      
      return $this;
    }

    /**
	* Метод для получения ОДНОЙ записи из БД. 
	* Т.к. драйвер может быть разным, метод может быть реализован по разному
	* 
	* @param string $sSql
	* 
	* @return object
	*/
    protected function _getRow($sSql)
    {
      $this->_oDB->setQuery($sSql);
      return $this->_oDB->loadObject();
	}

    /**
	* Метод для получения МАССИВА данных из БД. 
	* Т.к. драйвер может быть разным, метод может быть реализован по разному
	* 
	* @param string $sSql
	* 
	* @return array
	*/
    protected function _getRows($sSql)
    {
      $this->_oDB->setQuery($sSql);
      return $this->_oDB->loadObjectsList();
	}

    /**
	* Рекурсивное получение элементов из БД
	* 
	* @param int $id_parent
	* @param int $iLevel
	* 
	* @return
	*/
    protected function _getAllRecursively($id_parent, $iLevel = 0) 
    {
      $sSql = 'SELECT * FROM `tree` WHERE published=1 AND id_parent='.$id_parent.' ORDER BY ordering';
      $aRows = $this->_getRows($sSql);

      $aRet = array();
      $iNextLevel = $iLevel +1;

      if (count($aRows))
      {
        foreach($aRows as $oRow)
        {
          $oRow->__iLevel = $iLevel;

          $aSubRows = $this->_getAllRecursively($oRow->id, $iNextLevel);

          if (count($aSubRows))
          {
            $oRow->__aSubLevel = $aSubRows;
          }

          if(count($this->_aActivePath))
          {
            if(in_array($oRow->id, $this->_aActivePath))
            {
              $oRow->__isActive = TRUE;
            }
          }

          $aRet[] = $oRow;
        }
      }

      return $aRet;
    }

    /**
	* Возвращает дерево в виде массива
	* 
	* @param array $aOptions - массив с входными параметрами
	* 				int id_selected - активный элемент
	* 
	* @return array
	*/
    public function getItems($aOptions) 
    {
      $id_selected = isset($aOptions['id_selected'])?$aOptions['id_selected']:0;

      if($id_selected)
      {
        $this->_initActivePath($id_selected);	    
      }

      $aRet = $this->_getAllRecursively(0, 0);

      return count($aRet)?$aRet:[];
    }    


  }

Одио из двух представлений

ul.php (Download)

 <?

  /**
  * Представлени. Класс для формирует вывод дерева в UL>li список
  */
  class soViewTreeUL
  {

    /**
    * Формирует один уровень списка
    * 
    * @param array $aItems
	* @param int $iLevel
    * 
    * @return string
    */
    protected function _makeLevel(&$aItems, $iLevel = 0) 
    {
      $sRet = '';
      $iNextLevel = $iLevel + 1;
      foreach($aItems as $oItem)
      {
        $sRet .= '<li'.(isset($oItem->__isActive)?' class="active"':'').'>'.$oItem->title.'</li>';

        if(isset($oItem->__aSubLevel))
        {
          $sRet .= '<ul class="hidden" id="itm_'.$oItem->id.'">';
          $sRet .= $this->_makeLevel($oItem->__aSubLevel, $iNextLevel);
          $sRet .= '</ul>';
        }
      }

      //return ob_get_clean();
      return $sRet;
    }


    /**
    * Формирует вывод
    * 
    * @param array $aItems
    * 
    * @return string
    */
    public function render(&$aItems) 
    {
      return '<ul id="ul_menu">'.$this->_makeLevel($aItems, 0).'</ul>';
    }
  }


Скачать


Категории: PHP, Class
Яндекс.Метрика