laravel-nestedset
laravel-nestedset copied to clipboard
create() with children attribute throwing error
I am sending the following array to the create()
array(3) {
["name"]=>
string(4) "cat1"
["company_id"]=>
int(1)
["children"]=> array(1) {
array(2) {
["name"]=>
string(4) "cat2"
["company_id"]=>
int(1)
}
}
}
Those categories don't exist in my DB. But I do have other categories already. I want to create a new node being a root and its children.
It is creating only the first one cat1
without setting _lft
and _rgt
(both null in DB) attributes then it is throwing an Exception
Since the _lft
and _rgt
are being set with null on my parent category I get the following errors:
Node must exists.
at /vendor/kalnoy/nestedset/src/NodeTrait.php:1155
More of the stack trace:
#0 /vendor/kalnoy/nestedset/src/NodeTrait.php(435): App\Model\Category->assertNodeExists(Object(App\Model\Category))
#1 /vendor/kalnoy/nestedset/src/NodeTrait.php(412): App\Model\Category->appendOrPrependTo(Object(App\Model\Category))
#2 /vendor/kalnoy/nestedset/src/NodeTrait.php(766): App\Model\Category->appendToNode(Object(App\Model\Category))
#3 /vendor/kalnoy/nestedset/src/NodeTrait.php(775): App\Model\Category::create(Array, Object(App\Model\Category))
#4 App\Model\Category::create(Array)
Looking at the code I think there is a bug on the create() function creating the root node, like a missing call to makeRoot()
along with maybe some bug on the events for the children updates.
I solved the problem by directly calling action methods inside the create() function like this on NodeTrait(765):
if ($parent) {
$instance->appendToNode($parent);
$instance->actionAppendOrPrepend($parent);
} else if ($instance->getParentId() === null) {
$instance->actionRoot();
}
I know this isn`t the correct way of fixing it.
I also think it is important to mention I am partially using Laravel, I am just using Eloquent.
So my libs regarding illuminate are:
"illuminate/database": "^5.3",
"illuminate/support": "5.2.* | 5.3.* | 5.4.*",
"illuminate/events": "5.2.* | 5.3.* | 5.4.*",
"illuminate/contracts": "5.4.*",
"illuminate/container": "5.4.*",
"illuminate/pagination": "5.4.*"
Maybe this is due to a lack of dependency statement on composer.json
If you're using only Eloquent, you need it to generate events properly and for this, dispatcher should be set up
I have the events(which dispatcher is part of) lib like I mentioned in the end on the copy of part of my composer.json.
Yes, but you need to set dispatcher on Eloquent
Well, I have this slice of code here which I call on my index.php
file to boot the eloquent:
$capsule = new Illuminate\Database\Capsule\Manager();
$capsule->addConnection($container['eloquent']);
$capsule->setAsGlobal();
$capsule->bootEloquent();
on bootEloquent()
there is this:
// If we have an event dispatcher instance, we will go ahead and register it
// with the Eloquent ORM, allowing for model callbacks while creating and
// updating "model" instances; however, it is not necessary to operate.
if ($dispatcher = $this->getEventDispatcher()) {
Eloquent::setEventDispatcher($dispatcher);
}
I had a similar problem; I'm seeding a table (Category) with complex nested data using Phinx. In the seeder file (CategoriesSeeder.php - which extends AbstractSeeder) I have an init
method. In this very method I initialize a new Capsule (use Illuminate\Database\Capsule\Manager as Capsule;
, add it to a new connection, set as global... as @murilozilli did in there. And then in the run
method I set the model's event dispatcher like so;
Category::setEventDispatcher($this->capsule->getEventDispatcher());
Bam, events on the observer (CategoryObserver) working now. Hope this helps.
EDIT: Right after the line that sets the model's event dispatcher that line exists (the data below demonstration only) and works as expected;
Category::rebuildTree([
[
'name' => 'Category 1',
// other fields of Category instance for "Category 1" (if any)
'children' => [
'name' => 'Subcategory 1 of Category 1'
// other fields of Category instance for "Subcategory 1 of Category 1" (if any)
// children of "Subcategory 1 of Category 1" (if any)
]
],
[
'name' => 'Category 2',
// other fields of Category instance for "Category 2" (if any)
// children of "Category 2" (if any)
],
//
]);
Hi,
i have the same issue, tried the solution above to get an eventdispatcher instance, but: $capsule->getEventDispatcher() returns NULL.
I use eloquent outside laravel and initialize it exactly the way murilozilli does. Just the nestedset-trait does not work, it prints the same error as stated above =/
I know this is an old question but here is my solution. I'm working with eloquent outside laravel and initialize capsule in this way.
// Create new IoC Container instance
$container = new Container;
$container->bind('app', $container);
// Capsule
$capsule = new Capsule;
$capsule->addConnection([
'driver' =>'mysql',
'host' => $dbhost,
'database' => $dbname,
'username' => $dbuname,
'password' => $dbpass,
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => $prefix."_",
]);
$capsule->setEventDispatcher(new Dispatcher);
// Make this Capsule instance available globally via static methods... (optional)
$capsule->setAsGlobal();
// Eloquent
$capsule->bootEloquent();
$container->instance("capsule", $capsule);
Without this line,
$capsule->setEventDispatcher(new Dispatcher);
the code does not work.
Best regards