Nested Sets + CTreeView, CDropdownList, CListBox

Выкладываем свои наработки
Аватара пользователя
Darth_Ixis
Сообщения: 105
Зарегистрирован: 2010.08.23, 10:03
Откуда: KZ, Almaty

Re: Nested Sets + CTreeView, CDropdownList, CListBox

Сообщение Darth_Ixis » 2011.08.03, 11:02

Планируется ли введение возможности отключения транзакций внутри поведения?
Из-за отсутствия данной возможности нельзя самому инициализировать транзакции, как требуется.
Например, нельзя написать так:

Код: Выделить всё

    public function actionDelete($category_id)
    {
        if (Y::app()->request->isPostRequest) {
            try {
                $category = $this->loadModel($category_id);;
                $transaction = $category->dbConnection->beginTransaction();
                    if ($category->delete())
                        $transaction->commit();
                    else
                        throw new Exception($category->getErrors());
            }
            catch (Exception $e) {
               $transaction->rollBack();
               throw new CHttpException(400, $e->getMessage());
            }
        }
        else
            throw new CHttpException(400,'Invalid request. Please do not repeat this request again.');
    } 

Аватара пользователя
aleXoid
Сообщения: 6
Зарегистрирован: 2011.01.03, 17:48

Re: Nested Sets + CTreeView, CDropdownList, CListBox

Сообщение aleXoid » 2011.08.11, 16:08

zvnman писал(а):
Timlar писал(а):Я бы рекомендовал использовать вот это расширение: http://code.google.com/p/yiiext/source/ ... del/trees/. Сам с ним работаю, намного удобнее чем то, о котором говорится в данной теме.
А как используя данный класс вывести дерево в CtreeView?

Я просто доработал, используя обсуждаемое поведение, добавив к NestedSetBehavior:

Код: Выделить всё

...
public function getTreeViewData($rootNodeId = null, $isReturnRootNode = true){
        $keyField = 'id';

        if ($rootNodeId == null)
            $rawTree = $this->getTreeWithoutManyRoots();
        else
            $rawTree = $this->getTreeWithManyRoots($rootNodeId);

        // Init variables needed for the array conversion
        $tree = array();
        $node =& $tree;
        $position = array();
        $lastitem = '';
        $depth = 1;

        foreach($rawTree as $rawItem){
            // If its a deeper item, then make it subitems of the current item
            if ($rawItem->getLevelValue() > $depth)
            {
                $position[] =& $node; //$lastitem;
                $depth = $rawItem->getLevelValue();
                $node =& $node[$lastitem]['children'];
            }
            // If its less deep item, then return to a level up
            else
            {
                while ($rawItem->getLevelValue() < $depth)
                {
                    end($position);
                    $node =& $position[key($position)];
                    array_pop($position);
                    $depth = $node[key($node)]['node']->getLevelValue();
                }
            }

            if(!$rawItem->hasChildNodes())
                $rawItem->owner->name = '<a href="/category/'.$rawItem->owner->id.'">'.$rawItem->owner->name.'</a>';
            else
                $rawItem->owner->name = '<span>'.$rawItem->owner->name.'</span>';

            // Add the item to the final array
            $node[$rawItem->$keyField]['node'] = $rawItem;
            $node[$rawItem->$keyField]['id'] = (int) 'node'.$rawItem->owner->id;
            $node[$rawItem->$keyField]['text'] = (string) $rawItem->owner->name;
            // save the last items' name
            $lastitem = $rawItem->$keyField;
        }
        // we don't care about the root node
        if (!$isReturnRootNode){
            reset($tree);
            $tree = $tree[key($tree)]['children'];
            //array_shift($tree);
        }

        return $tree;
    }


    protected function getTreeWithoutManyRoots(){
        $owner=$this->getOwner();
        return $owner->findAll(array('order'=>$this->leftAttribute));
    }


    protected function getTreeWithManyRoots($rootId){
        $owner=$this->getOwner();
        return $owner->findAll(
            array(
                 'condition' => $this->rootAttribute.'=:rootId',
                 'order'=>$this->leftAttribute,
                 'params' => array(':rootId'=>$rootId)
            ));
    }


    protected function hasChildNodes(){
        return $this->getLeftValue() != ($this->getRightValue() - 1);
    }

    protected function getLeftValue(){
        $fieldName = $this->leftAttribute;
        $owner=$this->getOwner();

        return $owner->$fieldName;
    }

    protected function getRightValue(){
        $fieldName = $this->rightAttribute;
        $owner=$this->getOwner();

        return $owner->$fieldName;
    }


    protected function getLevelValue(){
        $fieldName = $this->levelAttribute;
        $owner=$this->getOwner();

        return $owner->$fieldName;
    }


    protected function getRootValue(){
        $fieldName = $this->rootAttribute;
        $owner=$this->getOwner();

        return $owner->$fieldName;
    }

 

E.l.l.a.r
Сообщения: 12
Зарегистрирован: 2011.08.14, 16:51

Re: Nested Sets + CTreeView, CDropdownList, CListBox

Сообщение E.l.l.a.r » 2011.08.18, 22:07

Подскаите, пожалуйста, как можно построить дерево, данные для которого получены в результате выполнения хранимой процедуры? ведь в этом случае модель с ActiveRecord не создать...

rak
Сообщения: 2021
Зарегистрирован: 2010.11.02, 23:40
Контактная информация:

Re: Nested Sets + CTreeView, CDropdownList, CListBox

Сообщение rak » 2011.08.18, 22:35

почему же не создать
вот тут можно почитать об этом
http://rmcreative.ru/blog/post/yii-obek ... at-vyborki

E.l.l.a.r
Сообщения: 12
Зарегистрирован: 2011.08.14, 16:51

Re: Nested Sets + CTreeView, CDropdownList, CListBox

Сообщение E.l.l.a.r » 2011.08.19, 09:13

А каким образом тогда определить класс AR, ведь получается, что

Код: Выделить всё

public function tableName()
    {
        return 'tbl_name';
    } 
не прокатит, так как таблицы то нету, соответственно и метаданные для создания класса получить неоткуда

E.l.l.a.r
Сообщения: 12
Зарегистрирован: 2011.08.14, 16:51

Re: Nested Sets + CTreeView, CDropdownList, CListBox

Сообщение E.l.l.a.r » 2011.08.26, 19:05

Далее в этой же директории создаем (если не существует) папку /views в которой создаем файл tree.php. Открываем его и пишем:

КОД: ВЫДЕЛИТЬ ВСЁ

<?php
$this->widget('CTreeView', array(
'data'=>$tree, // передаем массив
'animated'=>'medium', // скорость анимации свертывания/развертывания
'collapsed'=>true, // если тру, то при генерации дерева, все его узлы будут свернуты
'persist'=>'location', // метод запоминания открытого узла
'unique'=>true, // если тру, то при открытии одного узла, будут закрываться остальные
'cssFile'=>'/css/treeview/jquery.treeview.css', // меняем расположение css файла (он немного подправлен мной)
));
?>
что за метод запоминания открытого узла и где он прописан? а то у меня при переходе со страницы на страницу дерево снова все сворачивается

nigredo
Сообщения: 9
Зарегистрирован: 2011.12.07, 00:33
Откуда: Донецк,Украина

Re: Nested Sets + CTreeView, CDropdownList, CListBox

Сообщение nigredo » 2011.12.07, 00:44

Здравствуйте! Начал недавно учить yii.
И вот дошло дело до древовидных категорий, скачал отсюда http://code.google.com/p/yiiext/source/ ... del/trees/, behavior и подключил. Но при сохранении пишет ошибку:
You should not use CActiveRecord::save() method when NestedSetBehavior attached.
Подскажите пожалуйста, как решить эту проблему.

Аватара пользователя
timlar
Сообщения: 1382
Зарегистрирован: 2009.09.19, 17:49
Откуда: Украина, Днепропетровск
Контактная информация:

Re: Nested Sets + CTreeView, CDropdownList, CListBox

Сообщение timlar » 2011.12.07, 00:54

nigredo писал(а):Здравствуйте! Начал недавно учить yii.
И вот дошло дело до древовидных категорий, скачал отсюда http://code.google.com/p/yiiext/source/ ... del/trees/, behavior и подключил. Но при сохранении пишет ошибку:
You should not use CActiveRecord::save() method when NestedSetBehavior attached.
Подскажите пожалуйста, как решить эту проблему.
Данное расширение теперь находится здесь: https://github.com/yiiext/nested-set-behavior
Twitter: @timlar_ua

nigredo
Сообщения: 9
Зарегистрирован: 2011.12.07, 00:33
Откуда: Донецк,Украина

Re: Nested Sets + CTreeView, CDropdownList, CListBox

Сообщение nigredo » 2011.12.07, 01:02

Спасибо! скачал с новой ссылки, все равно та же ошибка. Ошибка возникает в behavior-функции beforeSave($event), если посмотреть код функции, то получается, что переменная $this->_ignoreEvent = false, но по логике функции должна быть true.

Аватара пользователя
timlar
Сообщения: 1382
Зарегистрирован: 2009.09.19, 17:49
Откуда: Украина, Днепропетровск
Контактная информация:

Re: Nested Sets + CTreeView, CDropdownList, CListBox

Сообщение timlar » 2011.12.07, 01:08

А код сохранения можно увидеть?
Twitter: @timlar_ua

nigredo
Сообщения: 9
Зарегистрирован: 2011.12.07, 00:33
Откуда: Донецк,Украина

Re: Nested Sets + CTreeView, CDropdownList, CListBox

Сообщение nigredo » 2011.12.07, 01:10

Использую все стандартное.
Контроллер:

Код: Выделить всё

    public function actionCreate()
    {
        $model = new Categories;

        // Uncomment the following line if AJAX validation is needed
        // $this->performAjaxValidation($model);

        $form = new CForm('application.views.categories.forms.categories', $model);

        if(isset($_POST['Categories']))
        {
            $model->attributes=$_POST['Categories'];
            if($model->save())    $this->redirect(array('view','id'=>$model->id));
        }

        $this->render('create',array(
            'form'=>$form,
        ));
    } 
В модели не переопределяю функцию save.

Аватара пользователя
timlar
Сообщения: 1382
Зарегистрирован: 2009.09.19, 17:49
Откуда: Украина, Днепропетровск
Контактная информация:

Re: Nested Sets + CTreeView, CDropdownList, CListBox

Сообщение timlar » 2011.12.07, 01:16

Нужно использовать не save(), а saveNode(). Рекомендую почитать мануал: https://github.com/yiiext/nested-set-be ... adme_ru.md
Twitter: @timlar_ua

nigredo
Сообщения: 9
Зарегистрирован: 2011.12.07, 00:33
Откуда: Донецк,Украина

Re: Nested Sets + CTreeView, CDropdownList, CListBox

Сообщение nigredo » 2011.12.07, 01:26

спасибо timlar! все работает.

nigredo
Сообщения: 9
Зарегистрирован: 2011.12.07, 00:33
Откуда: Донецк,Украина

Re: Nested Sets + CTreeView, CDropdownList, CListBox

Сообщение nigredo » 2011.12.08, 17:36

Подскажите, как использовать moveBefore и им подобные функции.
Пишу такой код:

Код: Выделить всё

        
$model = Categories::model();
$node = $model -> findByPK($id);        
$model -> moveAfter($node);
$this -> redirect(array('admin'));
 
Вылетает такая ошибка:

Код: Выделить всё

CDbCommand failed to execute the SQL statement: SQLSTATE[42000]: 
Syntax error or access violation: 1064 You have an error in your SQL syntax; 
check the manual that corresponds to your MySQL server version for the right syntax to use near 'AND `rgt`<=' at line 1. The SQL statement executed was: UPDATE `categories` SET `level`=`level`+2 WHERE `lft`>= AND `rgt`<= 
 

Аватара пользователя
timlar
Сообщения: 1382
Зарегистрирован: 2009.09.19, 17:49
Откуда: Украина, Днепропетровск
Контактная информация:

Re: Nested Sets + CTreeView, CDropdownList, CListBox

Сообщение timlar » 2011.12.08, 17:59

Нужно получить модель обеих нод, и только потом перемещать.
Twitter: @timlar_ua

nigredo
Сообщения: 9
Зарегистрирован: 2011.12.07, 00:33
Откуда: Донецк,Украина

Re: Nested Sets + CTreeView, CDropdownList, CListBox

Сообщение nigredo » 2011.12.08, 19:31

то есть еще нужно получить модель ноды стоящей выше/ниже перемещаемой, и передавать ее в moveAfter() ?

Аватара пользователя
timlar
Сообщения: 1382
Зарегистрирован: 2009.09.19, 17:49
Откуда: Украина, Днепропетровск
Контактная информация:

Re: Nested Sets + CTreeView, CDropdownList, CListBox

Сообщение timlar » 2011.12.08, 22:00

nigredo писал(а):то есть еще нужно получить модель ноды стоящей выше/ниже перемещаемой, и передавать ее в moveAfter() ?
Да
Twitter: @timlar_ua

Аватара пользователя
pls-kick-me
Сообщения: 42
Зарегистрирован: 2011.02.05, 22:39
Откуда: Украина, Донецк

Re: Nested Sets + CTreeView, CDropdownList, CListBox

Сообщение pls-kick-me » 2011.12.15, 19:41

Простите, что эту тему муссирую, но может кто нить обьяснить зачем вообще этот зверь ? и для чего нужен behaviour ?
Спасибо.
Yes I'm Insistent

esche
Сообщения: 1054
Зарегистрирован: 2010.11.24, 03:39

Re: Nested Sets + CTreeView, CDropdownList, CListBox

Сообщение esche » 2011.12.15, 22:06

pls-kick-me писал(а):Простите, что эту тему муссирую, но может кто нить обьяснить зачем вообще этот зверь ? и для чего нужен behaviour ?
Спасибо.
Кто зверь о_О? NestedSets?
http://libkal.gr/yii_lab/category/admin_grid

А для чего нужен behavior он же некий миксин на самом деле никто толком не знает - все пользуют как хотят :)
viewtopic.php?f=3&t=1219
viewtopic.php?f=8&t=10&hilit=behavior
viewtopic.php?f=9&t=3718
viewtopic.php?f=9&t=534
И вообще
...

Аватара пользователя
pls-kick-me
Сообщения: 42
Зарегистрирован: 2011.02.05, 22:39
Откуда: Украина, Донецк

Re: Nested Sets + CTreeView, CDropdownList, CListBox

Сообщение pls-kick-me » 2011.12.16, 00:37

уважил, дай Бог тебе здоровья для программирования )
Yes I'm Insistent

Ответить