lazychaser / laravel-nestedset Goto Github PK
View Code? Open in Web Editor NEWEffective tree structures in Laravel 4-8
Effective tree structures in Laravel 4-8
Hello,
I have a variable containing the full "path" (string with name and name of all parents seperated by |) of a category. For example "store|notebooks|apple"
. Now I would like to get the right category mathing this string. Sure, i could do Category::byName("apple")
but if apple also exists in the mobile
category this won't work.. Is there a nice way to do this?
I have a large table of geography data that I'm interested in testing nested sets out with, what is the bets way to generate a node from an already-existing record without having to delete and re-create it?
- Removing laravel/framework (v5.1.8)
- Installing laravel/framework (v5.1.9)
Downloading: 100%
[ErrorException]
Declaration of Kalnoy\Nestedset\Node::append() should be compatible with Illuminate\Database\Eloquent\Model::append($attributes)
Into the new version of framework to the "Model" class was added new feature, that have same name as the "Node" class function - append, but have different signature.
laravel/framework@2f96281
I apologise for my bad english.
Hi!
I am using custom BaseModel (which extends Eloquent) across my whole project. I want \Kalnoy\Nestedset\Node class to extend my BaseModel. Currently I have custom Node class which is identical copy of \Kalnoy\Nestedset\Node. I know this is dirty hack but is there a cleaner and easier way to achieve this?
Thank you in advance!
Hi,
Any plans on making it compatible with Laravel 4.2? Would love to keep using this package!
Hello Kalnoy and congratulations for your great work,
I would like to ask if you can be so kind to make the documentation a little more friendly and informative. It really takes too much time to understand basic tasks. For example I have been trying to insert a single node (on an empty table) for about two hours. The solution is that one should insert a root record with value of 1 for _lft and value of 2 for _rgt. Adding more notes and examples to your work will be great; besides what is the point of having such useful extension if you don't know how to you use.
Thank you and good luck!
Is there a way to get a single ancestor?
Hello sir,
With the following code (regardless of what is inside the get()), I get a "Maximum function nesting level of '100' reached, aborting!" error:
$groups = ItemGroup::defaultOrder()->get(['name'])->toTree();
return $groups;
but this code works:
$groups = ItemGroup::defaultOrder()->get()->toTree();
return $groups;
The error appears to be a result of converting the tree to an array.
I've recenty updated Laravel to 4.2, and this issue also occurs with version 1.1. Perhaps I should stick with 4.1 for now?
Laravel 5.1.9 was released with a modification to the Illuminate\Database\Eloquent\Model
class. This modification added a new function called append() that now conflicts with the Kalnoy\Nestedset\Node::append()
method that previously existed in this package.
Is there any way to eager load descendants without having to iterate through each node?
Right now I'm having to do
foreach ($nodes as $node) {
$node->getDescendants();
}
It would be nice to do something like
$categories = Category::with('descendants')->get();
and the each category would have $category->descendants.
Hello,
I am a newbie so this is something I am probably missing. Everything was working great for me, then suddenly nothing saved as root. The lft and rgt columns are always 0. And I cannot save any children. The parent ID is never filled with the parent.
Any idea what could have broke?
Let's say i have a tree like in your documentation with the "Catalog" and i would like to get the nodes "Samsung" in "Mobile" and "Apple" in "Netbooks" including all ancestor nodes up to the root, but without the root. All other nodes should not be included in the tree.
My code now looks like this:
$channels = array(4, 6);
Channel::withoutRoot()->whereIn('id', $channels)->get()->toTree();
But then i would only get the nodes "Samsung" and "Apple" and not the ancestor elements and so no tree could be built. Think of it as "a user has access on only specific nodes and the tree should be displayed up to the root".
I could get the specific nodes and built the tree up with one query per node, but this would be extremly overhead. Do you have any ideas?
First of all, спасибо! :)
I add these lines to my Category model and after that SoftDeletes start working as expected. May be I misunderstood something and my code have logical mistakes, check please:
protected static function signOnEvents() {
static::saving(function (Node $model) {
return $model->callPendingAction();
});
static::deleting(function (Node $model) {
if ($model->hardDeleting()) $model->refreshNode();
});
static::deleted(function (Node $model) {
$model->deleteNode();
});
static::restoring(function (Node $model) {
$model->restoreNode();
});
}
public function newServiceQuery() {
return $this->newQuery();
}
protected function restoreNode() {
if ($last = $this->siblings()->reversed()->first()) {
$lft = $last->getRgt() + 1;
} elseif ($this->getParentId()) {
$parent = $this->parent()->first();
$lft = $parent->getLft() + 1;
} else {
$lft = 1;
}
$this->setAttribute(static::LFT, $lft);
$this->setAttribute(static::RGT, $lft + 1);
$this->makeGap($lft, 2);
return true;
}
protected function hardDeleting() {
return !$this->softDeleting();
}
protected function softDeleting() {
return static::$_softDelete && !$this->forceDeleting;
}
Checks in QueryBuilder::countErrors()
must exclude rows which are soft deleted.
[ErrorException]
Declaration of Kalnoy\Nestedset\Node::append() should be compatible with Illuminate\Database\Eloquent\Model::append($attributes)
Hi,
Thanks for the package. One thing that I find it lacks is the data integrity check like in CakePHP's Tree, for example: http://book.cakephp.org/2.0/en/core-libraries/behaviors/tree.html#data-integrity
If you ever have time, it'd be great if this was introduced.
Hi lazychaser,
is it possible to use your package without using parent_id? I would like to use your nice package on existing nested set tables who are only provide lft and rgt. Unfortunately there is no way to create the parent_id column because some of these tabels needs to be shared with other applications.
Many thanks in advance
Dietmar
When performing Model::isBroken() QueryBuildier didn't take into consideration the database table prefix set up in config.
In Kalnoy\Nestedset\QueryBuilder
protected function wrappedTable()
{
return $this->query->getGrammar()->wrap($this->getQuery()->getConnection()->getTablePrefix() . $this->getQuery()->from);
}
Quick fix for this.
I've been digging into the package, it works great so far. But I was wondering if there was a way to generate the actual tree from a query. All I get is the nodes themselves but as a one dimension array.
Thanks,
M
when i extend my Category model class with Node and then call a route to save category I'm getting No query results for model [Category].
error
class Category extends Node {}
/**
* Store a newly created resource in storage.
*
* @return Response
*/
public function store()
{
// validate
$rules = array(
'title' => 'required',
'slug' => 'required',
'parent' => 'required|numeric'
);
$validator = Validator::make(Input::all(), $rules);
// process form
if ($validator->fails()) {
return Redirect::to('admin/categories')
->withErrors($validator)
->withInput(Input::all());
} else {
// store
$cat = new Category;
$cat->title = Input::get('title');
$cat->slug = Input::get('slug');
$cat->parent = Input::get('parent');
$cat->save();
// redirect
Session::flash('message', 'Category Successfully created!');
return Redirect::to('admin/categories');
}
}
Laravel 4.2 not supported
Is it possible to get all of the children at a certain level in the tree? When I recursively use getDescendants() to display the tree, I end up with repeated leaves. But If I could get only the descendants at a certain level, I would be able to recurse without repetition.
Hi,
First of all I would like to thank you for this awesome library. It saved me a lot of my time!
One question: Where are the consistency methods? I can't find them in source code. According to "documentation" I should use MyNode::isBroken()
or MyNode::countErrors()
but I get exception with message - Call to undefined method Kalnoy\Nestedset\QueryBuilder::countErrors().
My MyNode model is created by class MyNode extends Kalnoy\Nestedset\Node {}
I am using latest version.
Thank you!
Hi,
Recently I've upgraded package to 2.0. Then I ran PHPUnit tests and I've found that method insertBefore is not working properly.
My tree is:
Then I've got following code:
$node = new MyNode();
$node->name = 'Test';
$node->insertBefore(MyNode::find(3));
After this my tree is:
My tree is:
If I am correct then tree should be:
My tree is:
Hi,
This works fine on Laravel 5?
Thanks in advance!
Hi, I have problem with moving node to another parent, here is my function:
public function update($id, $data) {
$row = $this->model->find($id);
$parent = $this->model->find($data['parent_id']);
if ($row->appendTo($parent)->save()) {
$moved = $row->hasMoved();
//return $moved;
}
$row->fill($data);
return $row->save();
}
And the $moved return false.
Sorry to my English not good.
Thanks.
Hi, how to move the item to first root? If use saveAsRoot it will add to end of root
Can u plz explain how to seed a nested set model. I can't figure out how to fill in the fields.
Even when I try building a tree like demonstrated. It gives me an error saying:
Invalid argument supplied for foreach()
inNode.php line 758.
The seeding code is:
Department::create( [ 'name' => 'A', 'head_user_id'=>2222, 'admin_user_id'=>2222, 'children' => [ [ 'name' => 'B', 'head_user_id'=>1111, 'admin_user_id'=>1111, ], ], ]);
Is there a way to repair broken tree? For example, if parent_id
of some nodes have been changed manually by SQL and now Category::countErrors()
return wrong_parent = 3
.
First of all, thanks for all the great work you've done and shared with this project. If I could make one suggestion though, maybe you could include a simple on liner example for deleting a node in the documentation. I know it sounds silly, but long story short, other noobs like me could probably benefit from that. When I initially downloaded your library, I modified deleteNode() to be public because it seemed like that's what I was meant to use. After tracing through your code I found my mistake. but a sentence in the docs of what method to use might help someone else. ...even though this was a slap in the face fix for me :)
Thanks again!
This error breaks my stuff since latest update.
ErrorException in Node.php line 1195:
Declaration of Kalnoy\Nestedset\Node::append() should be compatible with Illuminate\Database\Eloquent\Model::append($attributes)
Hi, just curious how to change the node position? Which code should I used?
Drag Product 2 from Product 1 to Product 3
Before :
Product 1
-Product 2
Product 3
After :
Product 1
Product 3
-Product 2
Drag Product 2 to Product 1
Before :
Product 1
Product 2
Product 3
After :
Product 1
-Product 2
Product 3
Drag Product 2 from Product 1 to root
Before :
Product 1
-Product 2
Product 3
After :
Product 1
Product 2
Product 3
Hi,
Recently I've upgraded package to 2.0. Then I ran PHPUnit tests and I've found that method insertAfter is not working properly.
My tree is:
Then I've got following code:
$node = new MyNode();
$node->name = 'Test';
$node->insertAfter(MyNode::find(2));
After this my tree is:
My tree is:
If I am correct then tree should be:
My tree is:
When the query builder is used in combination with joins, the parent_id (and probably others) column is ambiguous:
"SQLSTATE[23000]: Integrity constraint violation: 1052 Column 'parent_id' in where clause is ambiguous (SQL: select count(*) as aggregate from (select '1' as row from
products
left joinshops
onshops
.id
=products
.shop_id
left joincategories
oncategories
.id
=products
.category_id
whereparent_id
is null) AS count_row_table)"
using the following query:
$products = \Product::whereIsRoot()
->leftJoin('shops', 'shops.id', '=', 'products.shop_id')
->leftJoin('categories', 'categories.id', '=', 'products.category_id')
->select(['products.id', 'shops.name as shop', 'products.image', 'products.brand', 'products.name',
'products.unit', 'products.similarity', 'categories.name as category'
]);
For myself I quickly fixed it in QueryBuilder.php by altering the whereIsRoot() method to:
public function whereIsRoot()
{
$this->query->whereNull($this->model->getTable().'.'.$this->model->getParentIdName());
return $this;
}
But I think there are multiple places in the query builder that are incompatible with joins (still have to encounter them).
There seems to be a problem with tree updating.
Let's suppose I have a simple 2 level tree created using the model methods create()
and append()
, i.e. only a root node and a couple children. The tree is correct in the begining.
Now, if I replace the whole 2nd level, i.e. everything under my root node, and append new nodes to the root node, the _lft
and _rgt
numbers for the first appended child outbound the parents'. Despite the children()
method returning all the children nodes (because the parent_id
property links them correctly), a call to descendantsOf()
, which traverses the tree using the _lft
and _rgt
numbers, leave the first child out.
The procedure I used to replace the 2nd level is by calling delete()
on every child to be removed and then calling append()
on the root node for each new child. It is always the first newly appended child which is left out because the _lft
and _rgt
numbers on the parent don't include this child's ones.
fdafda
Hi @lazychaser, I am currently using this package and so far I like it. But I got stuck in one part that probably is possible to do but I haven't found solution in documentation. 😄
Can I use "create" method to update or delete all nodes which are not present in scope?
I need some method that'll do same job as seeding/mass assingment methods in etrepat/baum project.
In my example, I am trying to make forum where user can reorder the display of forum and subforum categories.
Thank you 😄
Declaration of Kalnoy\Nestedset\Node::append() should be compatible with Illuminate\Database\Eloquent\Model::append($attributes).
Maybe we can fix this to rename append to appendNode and appendTo to appendNodeTo. But this will break the the backwards compatibility, so maybe someone has a better idea?
Hi
I'm getting all pages with
$pages = $page->children()->get()->linkNodes();
and the presenter works fine on root nodes, but it doesn't work on children when I loop through them
@if($page->children()->count())
@foreach($page->children()->get() as $page)
{{ $page->urlTo }}
@endforeach
@endif
I'm rewriting a site from L4 to L5 and would be nice to be able to reuse as much code as possible...
I originally used a different package (baum/baum), but it's not in development anymore
I have a 360-node tree with N degrees of depth. The tree (represented by a model called TreeNode
) will be accessed frequently, but altered very infrequently.
I'm trying to build output similar to the following, in order to build a select dropdown of similar structure.
Product
Product > Category A
Product > Category A > Subcategory 1
Product > Category A > Subcategory 2
Product > Category B
Product > Category C
Product > Category C > Subcategory 1
Product > Category C > Subcategory 1 > Subcategory (a)
Product > Category D
Product > Category D > Subcategory 1
Product > Category D > Subcategory 2
...
In order to do this, I have created a method in my TreeNode
model called getPath()
:
public function getPath() {
$ancestors = $this->getAncestors(['Name']);
return implode(' > ',array_merge(array_column($ancestors->toArray(),'Name'),array($this->Name)));
}
Then I iterate over the results of a TreeNode::all()
and call getPath()
for each one.
@foreach( TreeNode::all() as $node )
{{ $node->getPath() }}<br />
@endforeach
Although the correct output is produced, the problem here is that this method takes 360 database queries build this tree, and if the list of nodes grows the problem will only compound. I have a feeling I'm doing this wrong, but looking through the code for laravel-nestedset
I haven't been able to find an alternative way to build the entire tree.
Is there a more efficient way to do this?
Thanks
Thanks for the package, it looks perfect for building a tree view in my app.
That said, when I reorder the nodes, using down() and up(), I can see they left and right values adjusting, but I can't find any way to read them back in the new order. Instead, they're always returned in the same order, which I guess is the original insertion order, even if I call the toTree method.
Is there any method provided to do this sorting or is up to me to do it manually?
N
Can you update URLs in packagist. Now there is no "4" in laraver.
I can't install this package using composer
- Installing kalnoy/nestedset (v1.1)
Downloading: connection...
Could not fetch https://api.github.com/repos/lazychaser/laravel4-nestedset/zipball/6748af4c27e455f64aea41bcfc550083be233b51, enter your GitHub credentials to access private repos
Hi, there is a typo in $column_s_ in Node.php Line 932:
public function getSiblings(array $column = array('*'))
{
return $this->siblings()->get($columns);
}
What is the idea behind deferred, single action anyway? If I call appendTo I want queries to DB happening.
parent_id, _lft,_rgt fields must be defined as protected properties to make them overridable.
The package still does not support 4.2
при использовании функции ancestorsOf($obj->id) увидел что нужна колонка ancestors_of в таблице модели. добавил колонку. но при создании новых строк она не заполняется. все значения NULL. я что-то не так делаю?
собственно изначальная цель - получить всех предков узла. это для построения хлебных крошек для текущего пункта меню.
Hi @lazychaser, this looks like an awesome package, nice work 😄
How would you go about having multiple nested set trees in the same database table?
Would simply having multiple roots work? So modifying one tree won't affect any of the other trees.
etrepat/baum has the concept of Scope. I was just wondering if this is possible with your package?
Thank you 😄
Hello,
When I execute in Laravel 5 the artisan command:
php artisan ide-helper:generate
An exception appears.
Exception: Declaration of Kalnoy\Nestedset\Node::newFromBuilder() should be compatible with Illuminate\Database\Eloquent\Model::newFromBuilder($attributes = Array, $connection = NULL)
Skipping \Kalnoy\Nestedset\Node.
I see you make the changes in Laravel 4 of
public function newFromBuilder($attributes = array(), $connection = null)
, but not in Laravel 5.
Do you plan to add this modification in Laravel 5?
Thanks
I'm having trouble understanding how to save a root node.
I've tried:
{{{Category::create([
'title' => 'Logos',
'slug' => 'logos',
'description' => 'blah bluh ipsum ma',
'_lft' => 0,
'_rgt' => 0
]);}}}
But I've a feeling I shouldn't specify _lft _rgt manually and that should managed by the script itself on first create.
Am I wrong in assumptions?
Tag last fix: newFromBuilder
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.