lazychaser / laravel-nestedset

Effective tree structures in Laravel 4-8
3.65k stars 473 forks source link

Does the id of model have to be incrementing integer? #157

Open chao opened 7 years ago

chao commented 7 years ago

Here is the code of my role model, it has a primary key id which is a unique string.

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Kalnoy\Nestedset\NodeTrait;

class Role extends Model
{
    use NodeTrait;

    protected $primaryKey = 'id';
    public $incrementing  = false;

    protected $fillable = ['id', 'name', 'description'];

    public $timestamps = false;
}

Here is my database migration code:

        Schema::create('roles', function (Blueprint $table) {
            $table->string('id', 50)->comment('Role ID');
            $table->String('name', 50)->comment('Role Full Name');
            $table->string('description', 200)->nullable()->comment('Description of role');
            $table->integer('_lft')->unsigned();
            $table->integer('_rgt')->unsigned();
            $table->string('parent_id', 50)->nullable();
            $table->index(['_lft', '_rgt', 'parent_id']);
            $table->primary('id');
        });

Right now I can create or get a tree, but when I try to delete a node, I got an exception InvalidArgumentException with message 'Model must be node.'

It would be nice if you allow the primary key to be a string value.

Thanks.

lazychaser commented 7 years ago

Please provide full exception description with call stack.

chao commented 7 years ago

Here is the log when I try to do a $role->delete();

[2016-11-21 14:13:10] local.ERROR: InvalidArgumentException: Model must be node. in /var/www/html/vendor/kalnoy/nestedset/src/DescendantsRelation.php:33
Stack trace:
#0 /var/www/html/vendor/kalnoy/nestedset/src/NodeTrait.php(275): Kalnoy\Nestedset\DescendantsRelation->__construct(Object(Kalnoy\Nestedset\QueryBuilder), Object(App\Models\Role))
#1 /var/www/html/vendor/kalnoy/nestedset/src/NodeTrait.php(651): App\Models\Role->descendants()
#2 /var/www/html/vendor/kalnoy/nestedset/src/NodeTrait.php(66): App\Models\Role->deleteDescendants()
#3 [internal function]: App\Models\Role::Kalnoy\Nestedset\{closure}(Object(App\Models\Role))
#4 /var/www/html/vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php(221): call_user_func_array(Object(Closure), Array)
#5 /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php(1665): Illuminate\Events\Dispatcher->fire('eloquent.delete...', Array)
#6 /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php(1121): Illuminate\Database\Eloquent\Model->fireModelEvent('eloquent.delete...', false)
#7 /var/www/html/app/Http/Controllers/Main/RoleController.php(29): Illuminate\Database\Eloquent\Model->delete()
#8 [internal function]: App\Http\Controllers\Main\RoleController->deleteRole('manager')
#9 /var/www/html/vendor/laravel/framework/src/Illuminate/Routing/Controller.php(55): call_user_func_array(Array, Array)
#10 /var/www/html/vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php(44): Illuminate\Routing\Controller->callAction('deleteRole', Array)
#11 /var/www/html/vendor/laravel/framework/src/Illuminate/Routing/Route.php(189): Illuminate\Routing\ControllerDispatcher->dispatch(Object(Illuminate\Routing\Route), Object(App\Http\Controllers\Main\RoleController), 'deleteRole')
#12 /var/www/html/vendor/laravel/framework/src/Illuminate/Routing/Route.php(144): Illuminate\Routing\Route->runController()
#13 /var/www/html/vendor/laravel/framework/src/Illuminate/Routing/Router.php(642): Illuminate\Routing\Route->run(Object(Illuminate\Http\Request))
#14 /var/www/html/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): Illuminate\Routing\Router->Illuminate\Routing\{closure}(Object(Illuminate\Http\Request))
#15 /var/www/html/app/Http/Middleware/SiteMiddleware.php(25): Illuminate\Routing\Pipeline->Illuminate\Routing\{closure}(Object(Illuminate\Http\Request))
#16 /var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(137): App\Http\Middleware\SiteMiddleware->handle(Object(Illuminate\Http\Request), Object(Closure))
#17 /var/www/html/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(33): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#18 /var/www/html/vendor/laravel/framework/src/Illuminate/Routing/Middleware/SubstituteBindings.php(41): Illuminate\Routing\Pipeline->Illuminate\Routing\{closure}(Object(Illuminate\Http\Request))
#19 /var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(137): Illuminate\Routing\Middleware\SubstituteBindings->handle(Object(Illuminate\Http\Request), Object(Closure))
#20 /var/www/html/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(33): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#21 /var/www/html/vendor/laravel/framework/src/Illuminate/Auth/Middleware/Authenticate.php(43): Illuminate\Routing\Pipeline->Illuminate\Routing\{closure}(Object(Illuminate\Http\Request))
#22 /var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(137): Illuminate\Auth\Middleware\Authenticate->handle(Object(Illuminate\Http\Request), Object(Closure))
#23 /var/www/html/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(33): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#24 /var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php(65): Illuminate\Routing\Pipeline->Illuminate\Routing\{closure}(Object(Illuminate\Http\Request))
#25 /var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(137): Illuminate\Foundation\Http\Middleware\VerifyCsrfToken->handle(Object(Illuminate\Http\Request), Object(Closure))
#26 /var/www/html/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(33): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#27 /var/www/html/vendor/laravel/framework/src/Illuminate/View/Middleware/ShareErrorsFromSession.php(49): Illuminate\Routing\Pipeline->Illuminate\Routing\{closure}(Object(Illuminate\Http\Request))
#28 /var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(137): Illuminate\View\Middleware\ShareErrorsFromSession->handle(Object(Illuminate\Http\Request), Object(Closure))
#29 /var/www/html/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(33): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#30 /var/www/html/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(64): Illuminate\Routing\Pipeline->Illuminate\Routing\{closure}(Object(Illuminate\Http\Request))
#31 /var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(137): Illuminate\Session\Middleware\StartSession->handle(Object(Illuminate\Http\Request), Object(Closure))
#32 /var/www/html/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(33): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#33 /var/www/html/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/AddQueuedCookiesToResponse.php(37): Illuminate\Routing\Pipeline->Illuminate\Routing\{closure}(Object(Illuminate\Http\Request))
#34 /var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(137): Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse->handle(Object(Illuminate\Http\Request), Object(Closure))
#35 /var/www/html/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(33): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#36 /var/www/html/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/EncryptCookies.php(59): Illuminate\Routing\Pipeline->Illuminate\Routing\{closure}(Object(Illuminate\Http\Request))
#37 /var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(137): Illuminate\Cookie\Middleware\EncryptCookies->handle(Object(Illuminate\Http\Request), Object(Closure))
#38 /var/www/html/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(33): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#39 /var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(104): Illuminate\Routing\Pipeline->Illuminate\Routing\{closure}(Object(Illuminate\Http\Request))
#40 /var/www/html/vendor/laravel/framework/src/Illuminate/Routing/Router.php(644): Illuminate\Pipeline\Pipeline->then(Object(Closure))
#41 /var/www/html/vendor/laravel/framework/src/Illuminate/Routing/Router.php(618): Illuminate\Routing\Router->runRouteWithinStack(Object(Illuminate\Routing\Route), Object(Illuminate\Http\Request))
#42 /var/www/html/vendor/laravel/framework/src/Illuminate/Routing/Router.php(596): Illuminate\Routing\Router->dispatchToRoute(Object(Illuminate\Http\Request))
#43 /var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(267): Illuminate\Routing\Router->dispatch(Object(Illuminate\Http\Request))
#44 /var/www/html/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): Illuminate\Foundation\Http\Kernel->Illuminate\Foundation\Http\{closure}(Object(Illuminate\Http\Request))
#45 /var/www/html/vendor/barryvdh/laravel-debugbar/src/Middleware/Debugbar.php(51): Illuminate\Routing\Pipeline->Illuminate\Routing\{closure}(Object(Illuminate\Http\Request))
#46 /var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(137): Barryvdh\Debugbar\Middleware\Debugbar->handle(Object(Illuminate\Http\Request), Object(Closure))
#47 /var/www/html/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(33): Illuminate\Pipeline\Pipeline->Il
luminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#48 /var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/CheckForMaintenanceMode.php(46): Illuminate\Routing\Pipeline->Illuminate\Routing\{closure}(Object(Illuminate\Http\Request))
#49 /var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(137): Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode->handle(Object(Illuminate\Http\Request), Object(Closure))
#50 /var/www/html/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(33): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#51 /var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(104): Illuminate\Routing\Pipeline->Illuminate\Routing\{closure}(Object(Illuminate\Http\Request))
#52 /var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(149): Illuminate\Pipeline\Pipeline->then(Object(Closure))
#53 /var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(116): Illuminate\Foundation\Http\Kernel->sendRequestThroughRouter(Object(Illuminate\Http\Request))
#54 /var/www/html/public/index.php(53): Illuminate\Foundation\Http\Kernel->handle(Object(Illuminate\Http\Request))
#55 {main}  

When I try to delete the role the method NestedSet::isNode($model) returned a FALSE value, however, when I do it in tinker it returned a TRUE value.

/var/www/html # php artisan tinker
Psy Shell v0.7.2 (PHP 7.0.12 — cli) by Justin Hileman
>>> $role = App\Models\Role::findOrFail('manager');
=> App\Models\Role {#771
     id: "manager",
     name: "业务经理",
     description: "样品库经理,具有基础的操作员权限,及额外的管理权限。",
     _lft: 5,
     _rgt: 6,
     parent_id: "operator",
   }
>>> Kalnoy\Nestedset\NestedSet::isNode($role)      
=> true
>>> 
chao commented 7 years ago

Well, I give up, I added a increment id for role table.

Garbee commented 7 years ago

In what context were you running $node->delete()? I'd assume from a PHP-FPM driven frontend instance, but just verifying. Right now running a test with UUID columns in tinker it works fine for me.

stian-scholtz commented 5 years ago

Was this ever solved? We are currently experiencing the same issue. Cannot delete node with UUID, but with incrementing integer it works fine.

scottlaurent commented 3 years ago

If anyone runs into this in the future, I added a PR to resolve this, but I was a bit rushed and I think the tests could be a bit cleaner as they are somewhat duplicated (though use UUID).

https://github.com/lazychaser/laravel-nestedset/pull/486