I have a little doubt: how do you create a CRUD for this kind of table?
I mean, when you crud the model, all you get is a form where you have to manually fill the root, left, right and level fields…this is not that easy imho and i’m sure you guys have solved this more elegantly
could you please share your experience on how to crud this model?
thank you very much, Samdark, i’m testing this right now…facing some troubles in rendering but have already posted in the EJNestedTreeActions forum topic
Ah sorry… I had validation in my model on lft / rgt / lvl… But the behavior runs after validation.
And I notice the root needst left = 1 / rgt = 2 else it will move the root to child
Any reason why there is not a addRoot method ?
Also it be nice to have some convience method to have the tree return in an multi dimensional associative array… As far as I can see now descendants()->findAll() just returns all records in a flat array.
Also how to get the the path? Like I select a category but want to get the entire path all the way up, usefull for breadcrumbs and filtering in categories.
like…
SELECT parent.name
FROM nested_category AS node,
nested_category AS parent
WHERE node.lft BETWEEN parent.lft AND parent.rgt
AND node.name = 'FLASH'
ORDER BY parent.lft;
Also I see now that my first error was because validation is called before the makeRoot function… maybe better to call this after the makeRoot so the model can still have validation rules. And not have to call validate = false
One more thing how to use the delete function? If just get the model instance and delete it will not be called… and will not remove the descendants. Shouldnt it use the beforeDelete event?
Because if i change it too:
/**
* Deletes node and it's descendants.
* @return boolean whether the deletion is successful.
*/
public function beforeDelete($event) {
parent::beforeDelete($event);
$owner=$this->getOwner();
if($owner->getIsNewRecord())
throw new CDbException(Yii::t('yiiext','The node cannot be deleted because it is new.'));
$transaction=$owner->getDbConnection()->beginTransaction();
try
{
$root=$this->hasManyRoots ? $owner->{$this->root} : null;
if($owner->isLeaf())
$result=$owner->delete();
else
{
$condition=$this->left.'>='.$owner->{$this->left}.' AND '.
$this->right.'<='.$owner->{$this->right};
if($root!==null)
$condition.=' AND '.$this->root.'='.$root;
$result=$owner->deleteAll($condition)>0;
}
if($result)
{
$first=$owner->{$this->right}+1;
$delta=$owner->{$this->left}-$owner->{$this->right}-1;
$this->shiftLeftRight($first,$delta,$root);
$transaction->commit();
return true;
}
}
catch(Exception $e)
{
$transaction->rollBack();
}
return false;
}
Both with the commented attributes set and unset. I feel this implementation detail should be hidden, I didn’t even know if the counters start at zero or one until I read some comments in this thread, and maybe it is hidden and I don’t have to care about it. Just still didn’t find out.
In the end, this always throws an exception “Many roots mode is off”. And since it’s a new record and since I can’t save the AR using CActiveRecord::save, I’m feeling kind of lost here.
In the end, I created the root node directly in the DB (lft:1, rgt:2, level: 1, root: null) and managed to insert a node using the following snippet of code:
Is there a chance to get some small code snippets for each of the provided API methods? For example it seems to me as if the saveNode method is useless in single root mode, but maybe I’m using it the wrong way.
I’m trying to understand what values are stored in the ‘root’ field and the ‘level’ field. I wouldn’t need to know this except that I’m building a backoffice administration app that we’ll most likely use to configure our categories. I want to make sure I use the correct logic so that this extension will work if and when I want to use it.