Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

help #1

Closed
nepster-web opened this issue Dec 9, 2013 · 13 comments
Closed

help #1

nepster-web opened this issue Dec 9, 2013 · 13 comments

Comments

@nepster-web
Copy link

Здравствуйте, я нашел ваш скрип и хотел проверить его в действии. Однако так и не смог разобраться как с ним работать.

Есть ли к нему какия-либо документация ?

@matperez
Copy link
Owner

matperez commented Dec 9, 2013

Здравствуйте. К сожалению документации нет. Возможно позже добавлю.

В целом использование аналогично другим подобным расширениям. Например этому http://www.yiiframework.com/extension/nestedsetbehavior/

Данное поведение нужно добавить в описание модели
public function behaviors()
{
return array(
'NestedSetBehavior'=>array(
'class'=>'ext.ActiveRecordMaterializedTreeBehavior',
);
}

Так же в базе необходимо добавить поля и и индексы для этих полей

path varchar(100) NOT NULL DEFAULT '.',
level int(11) NOT NULL DEFAULT '0',
position int(11) NOT NULL DEFAULT '1',

После этого для данной модели становятся доступны методы данного поведения, как-то так:

$model = new SomeModel();
$model->name = 1;
$model->save();
$model2 = new SomeModel();
$model2->name = 2;
$model2->save();
$model1->mode($model2);

@matperez
Copy link
Owner

matperez commented Dec 9, 2013

Подробнее о данном методе хранения можно почитать в этой серии постов http://habrahabr.ru/post/46659/ http://habrahabr.ru/post/47280/

@nepster-web
Copy link
Author

Да вот как раз посоветовали разбираться на основе НС, но все же не могу понять, как у вас тут устроенно добавление дочернего элемента к родителю.

    $root_user = UsersStructModel::model()->findByAttributes(array('user_id'=>1));
    $new_user = new UsersStructModel();
    $new_user->user_id = 2;
    $new_user->save();
    $root_user->move($new_user);

По нестеду как то вот так, но что оно ругает "Имя столбца должно быть строкой или массивом."

@matperez
Copy link
Owner

matperez commented Dec 9, 2013

Не могу придумать где может возникать такая ошибка. Возможно у вас не проходит валидация. Если возможно приведите полный trace path. И схему базы, в которой хранится дерево.

У меня все работает в таком виде:
$f2 = Folder::model()->findByPk(1054920);
/** @var Folder $f */
$f = Folder::model()->findByPk(1055054);
$f->move($f2);

@nepster-web
Copy link
Author

public function behaviors()
{
    return array(
        'nestedSetBehavior'=>array(
            'class'=>'ext.NestedSetBehavior.MaterializedPathBehavior',
            'pathField'     => 'path',
            'pathSeparator' => '.',
            'positionFiled' =>'position',
            'levelField'    =>'level',
        ),
    );
}

Модель, валидации нет. Модель полностью голая за исключением behaviors

Контроллер тестовый:

public function actionMp()
{  
    set_time_limit(0);
    $start = microtime(true);

    echo '<pre>';


    $f = UsersStructModel::model()->findByAttributes(array('user_id'=>1));
    $f2 = UsersStructModel::model()->findByAttributes(array('user_id'=>2));

    $f->move($f2);

    $time = microtime(true) - $start;
    printf('<br/>Скрипт выполнялся %.4F сек.', $time);

}

Честно говоря вообще не понятно что мы делаете с f f2, какой вообще атрибут добавляет новый path в структуру ?

Я честно сам бы даже написал документацию и отправил Вам, если бы только понять как это работает.

Имя столбца должно быть строкой или массивом.
черкает MaterializedPathBehavior.php(160): CActiveRecord->save()
и $f->move($f2);

Я пытаюсь к руту добавить дочерний элемент как на хабре.

Рут: 1
Дочка: 1.1

Таблица:
CREATE TABLE G_users_struct (
user_id int(11) unsigned NOT NULL,
position int(11) NOT NULL DEFAULT '1',
level int(11) NOT NULL DEFAULT '0',
path varchar(100) NOT NULL DEFAULT '.'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

@matperez
Copy link
Owner

matperez commented Dec 9, 2013

В посте на хабре в поле path прописываются абстрактные цифры (1.1.1). В данном варианте в path добавляются через точку идентификаторы родительских элементов. За сортировку отвечает параметр position. Параметр level введен для облегчения и ускорения выборки элементов одинакового уровня.

За правильную сортировку отвечает метод setPosition(), за само перемещение move(). Элемент у которого level = 0, path = '.' считается корневым. level =1, path = '.1.' - это ребенок корневого элемента с идентификатором 1.

@nepster-web
Copy link
Author

тоесть Ваш скрипт не добавляет именно запись с path, тут весь вопрос именно в этом =)
Я имею введу генерацию именно пути 1.1.1.2 и тп. ?

@matperez
Copy link
Owner

matperez commented Dec 9, 2013

Добавляет. Вот этот кусок кода из метода move()

        if ($target && $target->primaryKey) {
            if ($target->{$this->levelField} == $this->maxLevel) {
                $target = $target->parent;
            }
            $model->{$this->levelField} = $target->{$this->levelField} + 1;
            $model->{$this->pathField}  = $target->{$this->pathField} . $target->primaryKey . $this->pathSeparator;
            $this->{$this->positionFiled} = count($target->children) + 1;
            $target->addChild($model);
        } else {
            $model->{$this->levelField} = 0;
            $model->{$this->pathField} = $this->pathSeparator;
            $rootsCount = $model->countByAttributes(array(
                $this->pathField => $this->pathSeparator
            ));
            $model->{$this->positionFiled} = $rootsCount ? $rootsCount + ($new ? 0 : 1) : 0;
        }

@nepster-web
Copy link
Author

Все понятно в чем проблема, обязательное условие это наличие ПК в таблице.

Но от сюда последний вопрос:

    $f = UsersStructModel::model()->findByPk(234);

    $f2 = new UsersStructModel;
    $f2->user_id = 400;

    $f2->move($f);

Создается 400 пользователь и его путь: .1.234. Тоесть у нас крепиться ПК таблицы к path. Однако далее пути будут крайне великоватые если брать user_id за pk.

Это получается нужно обязательно еще 1 колонку с автоинкрементом ?

И там если что я разберусь, я могу Вам написать документацию не большую ? Вещь стоящая если разобраться.

@matperez
Copy link
Owner

matperez commented Dec 9, 2013

Использовал в базе с ~ 300 тыс элементов. Размера поля path для этого хватало. Данное ограничение задается параметром $maxLevel - по сути это <размер поля path>/<размер id отдельного элемента>.

На счет документации: да конечно, буду благодарен )

@nepster-web
Copy link
Author

А вы использовали данный скрипт на практике ? тут походу не правильно пересчитывается лвл или вообще не пересчитывается при перетаскивании веток с 1 в другую. + иногда всплывала бесконечная рекурсия при перемещении веток

@matperez
Copy link
Owner

Конкретно этот не использовал, могут быть и баги. Использовал аналогичный для kohana 2.4.

@nepster-web
Copy link
Author

в общем где-то тут случайно как то вышло, что при смене веток вгоняется бесконечная рекурсия. Собственно из-за этого пришлось отказаться от текущей реализации

@matperez matperez closed this as completed Aug 4, 2014
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants