etrepat / baum

Baum is an implementation of the Nested Set pattern for Laravel's Eloquent ORM.
http://etrepat.com/baum
MIT License
2.24k stars 459 forks source link

Mass updating tree #68

Open mbouclas opened 10 years ago

mbouclas commented 10 years ago

Is there a way to mass update the tree based on an array model which usually comes from Javascript? The usual case is that we have a JS tree to depict our tree, the user changes the tree and on submit we need to figure out what changed in order to update the DB. It would be incredibly useful if the array coming from the JS could be mapped using just one method. Is there anything like this? What is the recommended best practices in situations like this?

etrepat commented 10 years ago

Unfortunately there's no seeding (mass-assignment) functionality in Baum at the moment.

That said, I like the idea of having some method to seed the tree from an array of node attributes. I'm probably going to implement something like this for the next version, I cannot give you a time-frame but I hope it's not too much in the future.

mbouclas commented 10 years ago

thanks for the quick reply. The cartalyst module nested-sets has one (method that is) and it is very convinient indeed

ghost commented 10 years ago

I really like this idea, as I am in a similar situation with the tree being updated using javascript. The way I deal with the changes is by binding individual updates to the javascript functions. Ajax calls are performed every time a node is created / updated / moved or deleted

mbouclas commented 10 years ago

i do the same thing and it's uggly as hell. Also, on large trees it is very hard on the user.

johnrisby commented 10 years ago

Is there any progress on this yet etrepat please?

I'm in the same position. I am using jstree to re-order my tree, create and delete nodes etc.

At the moment I am pushing the JSON data back to my controller and I need a way to convert that into the baum object and save it.

I've written some code that manually inserts the data into the database using id and parent_id only (at the moment only in to a test table, not the live table). In theory I could do that and the rebuild the tree, but obviously it's not a very elegant - or even safe - way of doing it...

Presumably I could adapt my code to create a new node object and populate it manually by recursion (similar to what I am doing to create the sql for the above method). But if you - or someone else - has this code already done it seems a waste of time to try to do it myself.

Thanks John

etrepat commented 10 years ago

I've implemented some version of this. It's currently on develop. I'll bump version & merge into master pretty soon.

johnrisby commented 10 years ago

Thanks for posting this update. I'd just starting writing my own yesterday and got part way on it.

I appreciate this is in development, but sadly your implementation doesn't seem to do what I need in its present form. In my Category model I only have the basics (id, left, right etc), and I have the name/description etc of the category in another class linked to the category class.

But when I try to update the tree, it is trying to find the 'name' variable in the category model and the SQL is failing. Is there a way to easily make it aware of relationships with other classes?

Thanks

etrepat commented 10 years ago

The default implementation is now on master. I think it should cover most-usual use cases.

If I understood your use case, you'd need to make the attributes in every attribute some sort of relation aware. So you could say, for example:

Category::buildTree(['name' => 'Some', 'children' => [ ... lots ... ], 'language' => ['name' => 'es'], ...]);

Being language, in this case, a related model and name an attribute of language. Is something like this what you mean?

Maybe we can find some way to try and add this functionality to the current implementation.

johnrisby commented 10 years ago

I think so ;)

Basically this is what I have.

A standard Baum\Node model called Category.

A model (inherited from Eloquent) called CategoryDescription.

Category has

public function CategoryDescription() { return $this->hasOne('CategoryDescription','category_id'); }

and CategoryDescription has

public function category() { return $this->hasOne('Category','category_id'); }

The CategoryDescription model has the name field.

As your code works now, it is trying to add the name field to the categories database and the sql is, obviously, failing. But if it could be made relationship-aware, then it would ideally know that name isn't in the Category model but the CategoryDescription model.

If I need to put that in the array somehow, that's fine of course.

Does that make sense?

Thanks John

etrepat commented 10 years ago

Yes it makes perfect sense.

I'll see how we could make adding attributes to related models work.

johnrisby commented 10 years ago

Great, thank you!