Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

dmcglone27's avatar

combine roles

I'm looking for a solution and suggestions to combining the users roles if they happen to have more than one role so there isn't multiple records on the page...

This is what I've come up with so far. Would it be better to store multiple roles in the same db row as the user instead of one record per role? My db schema is below.

Controller

$getRoles = Role::all();

        $userRoles = User::whereHas('getRoles', static function ($query) use ($getRoles) {
            return $query->whereIn('name', $getRoles);
        })->get();


View

@foreach($userRoles as $user)
                    @foreach($user->getRoles as $role)
                        @if($role->name != 'members')
                            <div class="col-md-6 col-lg-3 ftco-animate">
                                <div class="staff">
                                    <div class="img-wrap d-flex align-items-stretch">
                                        <div class="img align-self-stretch"
                                             style="background-image: url(images/staff/{{ $user->img }}); background-size: 250px 320px"></div>
                                    </div>
                                    <div class="text d-flex align-items-center pt-3 text-center">
                                        <div>
                                            <h3 class="mb-5">{{ $user->name }}</h3>
                                            <span class="position mb-4">{{ $role->name  }}</span>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        @endif
                    @endforeach
                @endforeach

role_user_table

Schema::create('role_user', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->bigInteger('user_id')->unsigned();
            $table->bigInteger('role_id')->unsigned();
            $table->timestamps();

            $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
            $table->foreign('role_id')->references('id')->on('roles')->onDelete('cascade');
        });

roles_table

Schema::create('roles', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('name');
            $table->string('label')->nullable();
            $table->timestamps();

0 likes
9 replies
MichalOravec's avatar

User model with roles relationship.

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * The roles that belong to the user.
     */
    public function roles()
    {
        return $this->belongsToMany(Role::class);
    }
}

In controller get users with roles

$users = User::with('roles')->get();

In view show just role name for each user

@foreach($users as $user)
    <div class="col-md-6 col-lg-3 ftco-animate">
        <div class="staff">
            <div class="img-wrap d-flex align-items-stretch">
                <div class="img align-self-stretch"
                     style="background-image: url(images/staff/{{ $user->img }}); background-size: 250px 320px"></div>
            </div>
            <div class="text d-flex align-items-center pt-3 text-center">
                <div>
                    <h3 class="mb-5">{{ $user->name }}</h3>
                    <span class="position mb-4">{{ $user->roles->implode('name', ', ') }}</span>
                </div>
            </div>
        </div>
    </div>
@endforeach

Docs: https://laravel.com/docs/8.x/collections#method-implode

dmcglone27's avatar

Thank you. I had something similiar but it wasn't a good solution for me because I don't want to fetch any roles with the name 'member'.

What I have works great, but if 1 person has more than 1 role, that person appears on the page multiple times for each role, instead of displaying just once with their perspective roles.

I hope that makes sense.

MichalOravec's avatar

@dmcglone27 Use everything what I posted above, just change code in the controller to this

$users = User::with(['roles' => function ($query) {
    $query->where('name', '<>', 'members'); 
}])->get();
1 like
dmcglone27's avatar

Well well well, thank you.. I had this exact same thing before I got what I have above, BUT i was using != like this

$users = User::with(['roles' => function ($query) {
    $query->where('name', '!=', 'members'); 
}])->get();

Can I ask why you used '<>' instead?

And thank you for the help, I appreciate it. :-)

MichalOravec's avatar

!= and <> are same, so it just of your preference. I prefer to use <>.

@dmcglone27 If your issue is solved, mark this thread as solved. Thanks.

1 like
dmcglone27's avatar

Ok.. taking a closer look, this code does work, but it removes the word "members" not the profile of members.

MichalOravec's avatar
Level 75

@dmcglone27 You need to use whereHas for that.

$users = User::with(['roles' => function ($query) {
    $query->where('name', '<>', 'members');
}])->whereHas('roles', function ($query) {
    $query->where('name', '<>', 'members');
})->get();

or you can save closure to a variable

$users = User::with(['roles' => $closure = function ($query) {
    $query->where('name', '<>', 'members');
}])->whereHas('roles', $closure)->get();
1 like
dmcglone27's avatar

That's it! Thanks. Now I've got to work at understanding this!

jlrdw's avatar

To make sure a role matches a required role, something like:

    public static function chkRole($role = null)
    {
        $userrole = Auth::user()->role;
        $checkrole = explode(',', $userrole);
        if (in_array($role, $checkrole)) {
            return true;
        }
        return false;
    }

1 like

Please or to participate in this conversation.