laravel-nestedset
laravel-nestedset copied to clipboard
Creating new node fails when using $parent attribute.
I am using the following to create a new node.
$add = new mCategory;
$parent = mCategory::findOrFail(4);
$add->category_name = $request->category_name;
$add->notes = $request->notes;
$add->parent_id = $parent->category_id; #### This is line 114 referenced in the error below
$add->save();
But I get a ModelNotFoundException in Builder.php line 196 error, here is part of the error:
in Builder.php line 196
at Builder->findOrFail('4') in NodeTrait.php line 822
at fnCategory->setParentIdAttribute('4') in Model.php line 2922
at Model->setAttribute('parent_id', '4') in Model.php line 3465
at Model->__set('parent_id', '4') in fnCategoryController.php line 114
at fnCategoryController->store(object(Request))
at call_user_func_array(array(object(fnCategoryController), 'store'), array(object(Request))) in Controller.php line 76
at Controller->callAction('store', array(object(Request))) in ControllerDispatcher.php line 146
at ControllerDispatcher->call(object(fnCategoryController), object(Route), 'store') in ControllerDispatcher.php line 94
at ControllerDispatcher->Illuminate\Routing\{closure}(object(Request))
at call_user_func(object(Closure), object(Request)) in Pipeline.php line 52
at Pipeline->Illuminate\Routing\{closure}(object(Request))
at call_user_func(object(Closure), object(Request)) in Pipeline.php line 102
at Pipeline->then(object(Closure)) in ControllerDispatcher.php line 96
at ControllerDispatcher->callWithinStack(object(fnCategoryController), object(Route), object(Request), 'store') in ControllerDispatcher.php line 54
at ControllerDispatcher->dispatch(object(Route), object(Request), 'App\Http\Controllers\Finance\fnCategoryController', 'store') in Route.php line 174
at Route->runController(object(Request)) in Route.php line 140
at Route->run(object(Request)) in Router.php line 703
From the docs/readme page it says you can do this:
// #6 Using the parent attribute
$node->parent_id = $parent->id;
$node->save();
If however I do this instead:
$add = new mCategory;
$parent = mCategory::findOrFail(4);
$add->category_name = $request->category_name;
$add->notes = $request->notes;
###$add->parent_id = $parent->category_id; # Remove this attribute.
$add->appendToNode($parent)->save();
Then it works, and it adds the node to the correct parent of the tree.
I would prefer to use the first way. Am I doing something wrong there?
Thanks!
in Builder.php line 196
at Builder->findOrFail('4') in NodeTrait.php line 822
at fnCategory->setParentIdAttribute('4') in Model.php line 2922
this means that model with an id of 4
is not found
Yes, but it does exist.
And the model with id 4 IS found when doing the appendToNode($parent) method.
I can also do
return dd($parent->category_id);
And I get a result for that.
But when I assign that to the new $add->parent_id attribute.
$add->parent_id = $parent->category_id;
It fails.
The model exists and is found. Shouldn't I be able to assign it to the $add->parent_id attribute?
Seems like you're using category_id
as a primary key and you didn't specify it in Eloquent model
I have the following set in my eloquent model. I think that it is correct.
use Kalnoy\Nestedset\NodeTrait;
9
10 class fnCategory extends Model
11 {
12 //
13 use SoftDeletes;
14 use NodeTrait;
15
16
17 protected $table = 'fn_category';
18 protected $primaryKey = 'category_id';
19
20 protected function getScopeAttributes() {
21 return [ 'tree_hash' ];
22 }
....
You're using scope attributes but don't set one on new model, it tries to find parent model applying scope and does not succeed.
Also, parent_id accepts numeric value, if you've already fetched the model from database, it is better to use appendToNode
Ah, yes that makes sense. I am not applying the scope attribute to the new model.
Is there a way to apply the scope attribute to the new model?
If not, I will continue to use the appendToNode
attribute, since it is working.
Thank you for your help.
Scoping relies on attributes, you simply need to set them. In your case you can do either of following:
$model = mCategory::scoped([ 'tree_hash' => $hash ]);
or
$model = new mCategory;
$model->tree_hash = $hash;
I apologize for being slow, but I still can't quite get this to work.
Adding a new node works as you suggested above.
But, then when I try the following to update a child node to a new parent node, and I still get errors.
$node = mCategory::scoped(['tree_hash' => $hash])->findOrFail(24); // Current parent_id = 18 , want to change to 16
$parent = mCategory::scoped(['tree_hash' => $hash])->findOrFail(16);
// None of the following work, all give 'ModelNotFoundErrors'
$node->appendToNode($parent)->save();
$parent->appendNode($node);
$node->parent()->associate($parent)->save();
$node->parent_id = 16;
$node->save();
Hi !
I encountered a similar issue. Creating a model as follow would not work and return a "not found" exception :
$data = [
'name' => 'Some category',
'parent_id' => '6c5deea0-87ac-11ea-87aa-0d8e79776d7a',
'document_id' => '6b5d0250-87ac-11ea-83a9-f9f3a62e4dcf',
]
$category = Category::create($data);
The reason why it does not work is that my nested set model is scoped on document_id
and this index was last in the array (or at least after parent_id
) passed to create()
. I do not have a handle on the order of the array elements because they come out of a request.
My solution is then to reorder the array to make sure the scoped index is first (or at least before parent_id
) before passing it to the create()
function.
Maybe this operation could be done inside this package ?
@Julien1138 Hi,Julien My problem is the same as yours. Have you solved it?
@lazychaser Can you pay attention to this problem?Please
Hi !
I encountered a similar issue. Creating a model as follow would not work and return a "not found" exception :
$data = [ 'name' => 'Some category', 'parent_id' => '6c5deea0-87ac-11ea-87aa-0d8e79776d7a', 'document_id' => '6b5d0250-87ac-11ea-83a9-f9f3a62e4dcf', ] $category = Category::create($data);
The reason why it does not work is that my nested set model is scoped on
document_id
and this index was last in the array (or at least afterparent_id
) passed tocreate()
. I do not have a handle on the order of the array elements because they come out of a request. My solution is then to reorder the array to make sure the scoped index is first (or at least beforeparent_id
) before passing it to thecreate()
function.Maybe this operation could be done inside this package ?
My solution is then to reorder the array to make sure the scoped index is first (or at least before
parent_id
) before passing it to thecreate()
function.
@lazychaser hi, faced with that too
I've experienced this issue again today for the umpteenth time. We have to try different workarounds each time for different projects.
Having the same issue here, we have a scope property type
and when setting a parent_id
in the request, the check for the parent's validity doesn't correctly include the scope property:
select
*
from
"categories"
where
"categories"."type" is null -- This shouldn't be null
and "categories"."id" = '01gv64ktmc3kr054x2sf5hb4fe'
and "categories"."organization_id" = '01GPKGCY6BTDZM5P3J6M43ARJ1'
and "categories"."deleted_at" is null
limit
1
liuyong888
Thank You! 👍