creocoder / yii2-nested-sets

The nested sets behavior for the Yii framework.
Other
446 stars 129 forks source link

Custom value for the root attribute #5

Closed zhuravljov closed 10 years ago

zhuravljov commented 10 years ago

Доработан метод makeRoot(). Доработка дает возможность задавать пользовательское значение для rootAttribute. Это нужно в случае когда поле таблицы, которое обозначено как rootAttribute, связано по внешнему ключу с другой таблицей. В этом случае установка значения в rootAttribute по primaryKey не подходит.

creocoder commented 10 years ago

@zhuravljov Can you show detail examples why you need that?

zhuravljov commented 10 years ago

К примеру, есть две таблицы:

Когда для заданного поля добавляется первый корневой элемент через:

$model = new FieldItem();
$model->load($data)
$model->field_id = 123;
$model->saveNode();

метод saveNode() отваливается с ошибкой связи по внешнему ключу, потому что для новой записи он неявно использует makeRoot(), а makeRoot() в свою очередь игнорирует уже установленное в field_items.field_id значение и пытается установить туда автоинкрементальное значение из field_items.id добавленной записи.

creocoder commented 10 years ago

@zhuravljov Расширение работает верно, игнорируя значение. Корни это частный случай нод и должны храниться в той же таблице. Если для корней требуются какие то дополнительные поля, то это возможно сделать используя другую схему, при этом оставаясь в рамках классического NS.

Та структура которую вы показываете, с произвольными значениями в rootAttribute никакого отношения к классическому NS с множественными корнями не имеет. Это очень спорная "вариация на тему", не более. Поэтому такое изменение не может быть внесено в расширение.

zhuravljov commented 10 years ago

Если я не ошибаюсь, классический NS, по своей сути, накладывает ограничение при котором у дерева всегда один общий корень, и никак не регламентирует способ хранения нескольких деревьев в одной таблице. Поле из rootAttribute, в данном случае, это самый логичный отличительный признак для разных деревьев.

Можно построить и другую схему, добавить поле root, установить его в rootAttribute, отдать установку значения в него на откуп расширению. Но, при этом, уникальности значений root и field_id для каждого дерева всегда будут совпадать. Зачем плодить сущности, когда достаточно одного поля?

Моя доработка ведь не ломает общую логику работы расширения, она дает возможность в частном случае задать значение для rootAttribute из кода приложения. Если в коде приложения в rootAttribute ничего установлено не будет, то расширение отработает штатным способом.

creocoder commented 10 years ago

никак не регламентирует способ хранения нескольких деревьев в одной таблице

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

Моя доработка ведь не ломает общую логику работы расширения

У корня значение rootAttribute должно быть равно PK корня. Сам корень должен находиться в той же таблице, что и ноды. В перспективе могут появиться методы, которые опираются на эту аксиому и они не будут работать в данном случае.

Зачем плодить сущности, когда достаточно одного поля?

Есть решения без каких либо дополнительных полей. Вы можете связаться со мной по скайпу (id = creocoder) и я расскажу детальнее.