phplaravellaravelcollectivelaravel-permission

How to populate the select opition from Database - Spatie Permission package - Laravel


I was following the article to bring up front end UI for Spatie/permissions.

article

I was able to understand every part but I cant understand a specific portion,

Please navigate to the Roles Part, (please search for 'roles.edit', it will take directly to the section )

In the Edit view the author is using the code,

<h5><b>Assign Permissions</b></h5>
    @foreach ($permissions as $permission)
        {{Form::checkbox('permissions[]',  $permission->id, $role->permissions ) }}
        {{Form::label($permission->name, ucfirst($permission->name)) }}<br>
    @endforeach

My understanding is that the form collective uses third parameter as checked field.

when I run the output passed to the third field

{{$role->permissions }}

I am getting results in this format

[{"id":1,"name":"Permission","guard_name":"web","created_at":"2019-08-04 05:53:14","updated_at":"2019-08-04 05:53:14","pivot":{"role_id":9,"permission_id":1}},

I am not sure how the laravel collective is parsing the result.

Authors Controller for edit

 public function edit($id) {
        $role = Role::findOrFail($id);
        $permissions = Permission::all();
        return view('roles.edit', compact('role', 'permissions'));
    }

Here is how I overcame this, btw I am not using collective

My Edit controller

 public function edit($id)
    {
        $role = Role::find($id);
        $roles_permissions = Role::findByName($role->name)->permissions;
        $permissions = Permission::all();

        return view('admin.userrole.role.edit', compact('role', 'permissions','roles_permissions'));
    }

My Blade file

<h4>Assign Permission</h4>
        <div class='form-group'>
            <p>
                Existing Permissions:
                @foreach ($roles_permissions as $item)
                <span class="badge badge-success"> {{$item->name}}</span>
                @endforeach
            </p>
            <p> {{$role->permissions}}</p>
            <select name="permissions[]" id="permissions" multiple class="form-control">
                @foreach ($roles_permissions as $item)
                <option value="{{$item->id}}" selected hidden></option>
                <span class="badge badge-success"> {{$item->name}}</span>
                @endforeach
                <option value="" selected>
                </option>
                @foreach ($permissions as $permission)
                <option value="{{$permission->id}}" checked="{{$role->permissions}}">{!!ucfirst($permission->name)!!}
                </option>
                @endforeach
            </select>
        </div>

I am sure that this is not the right way of achieving this. Please do let me know how do I populate the permissions in the select field.

Note: If devoting the question, kindly do put a comment why. So that I could improve my presentation. I do appreciate your effort. Thank you


Solution

  • There are a couple of issues that should help you to get this working. The LaravelCollective form (HTML) library is fantastic, but it also takes a little getting used to.

    On the controller side, you are currently sending a list of full permission objects back to the form from this line:

     $permissions = Permission::all();
    

    Or, as the author's form is doing it, they are pulling just those permissions from the specific $role. Either way, the missing piece is that the controller is sending the full object back to the form, which won't work as it is currently coded. The select box needs just name and id.

    So the controller should gather just those fields using pluck:

     $permissions = Permission::orderBy('name')->pluck('name', 'id');
    

    Then, on your blade page, the choices in permissions will correctly line up with the select section:

    {{Form::select('permissions[]', $permissions, null, [//classes, placeholder, multiple, etc] ) }}
    

    Note a few things here - the $permissions are the second parameter, not third. Also, you do not need to specify the $permission->id, this is automatically done with the Collective via form-model-binding. Instead, use null and it will bind on the user that you have bound to the form. If you are not using form model binding, you can write it yourself using the 3rd parameter instead of null:

     {{Form::select('permissions[]', $permissions, (isset($user->permission_id)? $user->permission_id: [null=>'Please Select']), [//classes, placeholder, multiple etc] ) }}
    

    Form model binding is fantastic, and allows you to use null as above... it's not hard - you just need to open the form with the correct model. This is beyond the scope of this question, but take a look at the Collective docs for examples on how to do it.