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

TheSolarwin's avatar

Can't select surveys based on user groups

Hello everyone!

Can somebody help me with advice? My database consist of tables users , roles and role_user pivot table, because users can be in several groups. So far everything is good, but I also have table surveys and I can't figure out how to show surveys based on user group. There is one to many relationship between table users and surveys. Every survey has a field "subject" and "subject" values has the same names as values in table "roles" field "name".

I tried to select these surveys with many if else statements, but i am sure there should be better and easiest way.

Thank you in advance!

0 likes
16 replies
TheSolarwin's avatar

Here is my tables: https://ibb.co/SNtNfjW

and function to return surveys to users who are in admin group and show surveys which are created by current logged in user.

    public static function getSurveys(Request $request)
    {
        if(Role::find(1)->users()->where('id', auth()->id())->exists())  //if user is in first group (admin group) show all surveys
        {
            $surveys = Survey::orderBy('id', 'ASC')->get();
        }
        else   //else just show auth users surveys
        {
            $surveys = Survey::where('user_id', auth()->id())->id())->orderBy('id', 'ASC')->get();
        }

How could I display surveys for users that are not in admin group but in any other group? Every survey has a field "subject" and "subject" values has the same names as values in table "roles" field "name".

This is what i figured out, but i can't write code like this because there are many groups and survey table column "subject" have many different values.

        else if(Role::find(3)->users()->where('id', auth()->id())->exists())   //if user is in the third group
        {
            $surveys = Survey::where('user_id', auth()->id())->orWhere('subject', Role::where('id', 3)->value('name'))->orderBy('id', 'ASC')->get();
        }

I am stuck for days and hoping for some help.

TheSolarwin's avatar

@frankielee thank you for your reply. The problem is that every user can belong to more than one group. I am not sure how to check to which groups user belongs and then show surveys "that belongs" to these groups.

frankielee's avatar

@TheSolarwin What do you mean by group? how exactly you want to perform the filter?

Can you give a brief explanation with the example? From the tables, I don't any find any group column.

TheSolarwin's avatar

@frankielee sorry i wanted to say roles not group. I will try to explain.

I have following tables: users, roles, role_user (pivot table) and surveys (every user can have multiple surveys). When user are logged in, I want to show them list of surveys based on their roles. For example there is a survey where field "subject" value is "Finance" and another survey where field "subject" value is "Marketing". There are user with name John, who is member of role with id=2 and role with id=3. Role with id=2 name is "Finance" and role with ID=3 name is "Marketing". There are many other roles.

The problem is - how could I show all surveys based on the current user roles?

TheSolarwin's avatar

@frankielee thanks, this is my Survey model now:

class Survey extends Model
{
    use HasFactory;

    public function role()
    {
        return $this->belongsTo(Role::class);
    }
}

Here is my controller:

    public static function getSurveys(Request $request)
    {
        $surveys  =  auth()->user()->load('surveys.role');
        return view('surveys',compact('surveys'));
	}

Here is response. Still not sure how to get further...

App\Models\User {#1136 ▼
  #fillable: array:4 [▶]
  #hidden: array:4 [▶]
  #casts: array:1 [▶]
  #appends: array:1 [▶]
  #connection: "mysql"
  #table: "users"
  #primaryKey: "id"
  #keyType: "int"
  +incrementing: true
  #with: []
  #withCount: []
  +preventsLazyLoading: false
  #perPage: 15
  +exists: true
  +wasRecentlyCreated: false
  #attributes: array:14 [▶]
  #original: array:14 [▶]
  #changes: []
  #classCastCache: []
  #dates: []
  #dateFormat: null
  #dispatchesEvents: []
  #observables: []
  #relations: array:1 [▼
    "surveys" => Illuminate\Database\Eloquent\Collection {#1387 ▼
      #items: array:31 [▼
        0 => App\Models\Survey {#1391 ▶}
        1 => App\Models\Survey {#1392 ▶}
        2 => App\Models\Survey {#1393 ▶}
        3 => App\Models\Survey {#1394 ▶}
        4 => App\Models\Survey {#1395 ▶}
        5 => App\Models\Survey {#1396 ▶}
        6 => App\Models\Survey {#1397 ▶}
        7 => App\Models\Survey {#1398 ▶}
        8 => App\Models\Survey {#1399 ▶}
        9 => App\Models\Survey {#1400 ▶}
        10 => App\Models\Survey {#1401 ▶}
        11 => App\Models\Survey {#1402 ▶}
        12 => App\Models\Survey {#1403 ▶}
        13 => App\Models\Survey {#1404 ▶}
        14 => App\Models\Survey {#1405 ▶}
        15 => App\Models\Survey {#1406 ▶}
        16 => App\Models\Survey {#1407 ▶}
        17 => App\Models\Survey {#1408 ▶}
        18 => App\Models\Survey {#1409 ▶}
        19 => App\Models\Survey {#1410 ▶}
        20 => App\Models\Survey {#1411 ▶}
        21 => App\Models\Survey {#1412 ▶}
        22 => App\Models\Survey {#1413 ▶}
        23 => App\Models\Survey {#1414 ▶}
        24 => App\Models\Survey {#1415 ▶}
        25 => App\Models\Survey {#1416 ▶}
        26 => App\Models\Survey {#1417 ▶}
        27 => App\Models\Survey {#1418 ▶}
        28 => App\Models\Survey {#1419 ▶}
        29 => App\Models\Survey {#1420 ▶}
        30 => App\Models\Survey {#1421 ▶}
      ]
    }
  ]
  #touches: []
  +timestamps: true
  #visible: []
  #guarded: array:1 [▶]
  #rememberTokenName: "remember_token"
  #ldapUserModel: null
}
frankielee's avatar

@TheSolarwin

You mean how to show the value? Just use the foreach loop. Did you need to return the user object as well?

if user object is not required, just use

$surveys = Survey::where('user_id',auth()->id)->with('role')->get()

https://laravel.com/docs/8.x/eloquent-relationships#many-to-many-polymorphic-retrieving-the-relationship

Example:

foreach($user->sureys as $survey){
	//do anything you want here
	dump($survey,$survey->role);
	
}

Blade https://laravel.com/docs/8.x/blade#loops

TheSolarwin's avatar

@frankielee thank you for your patience. I just want to return Surveys object (list of surveys that are related to current users roles). My Survey model have this:

    public function role()
    {
        return $this->belongsTo(Role::class);
    }
}

Controller:

    public static function getSurveys(Request $request)
    {
        $user = User::where('id', auth()->id());
        $surveys = Survey::where('user_id', auth()->id())->with('role')->get();
	}

View returns "ExceptionProperty [surveys] does not exist on the Eloquent builder instance".

        foreach($user->surveys as $survey){
            dump($survey,$survey->role);
            //shows ExceptionProperty [surveys] does not exist on the Eloquent builder instance.
        }

When i previously run dump on

        $surveys = Survey::where('user_id', auth()->id())->with('role')->get();

it shows:

  #relations: array:1 [▼
    "role" => null
  ]

It looks like there is no connection between survey and roles.

frankielee's avatar

@TheSolarwin

View returns "ExceptionProperty [surveys] does not exist on the Eloquent builder instance".

Because you are not using $user to load the surveys() relationship.

return $this->hasOne(Role::class, 'foreign_key', 'local_key');

https://laravel.com/docs/8.x/eloquent-relationships#one-to-one

You need to define the foreign key and local key. Because you are not linking the primary key of surveys

with the roles table.

Example:

return $this->hasOne(Role::class, 'user_id', 'user_id');

Btw, how do you know the role_id is belong to this user at this survey?

https://ibb.co/SNtNfjW I am not able find the connection between survey, user and role.

TheSolarwin's avatar

@frankielee sorry i dont understand this "Because you are not using $user to load the surveys() relationship.".

I edited my database structure, please take a look at my DB diagram: https://ibb.co/jD1Fg0m

Survey model:

    public function role()
    {
        return $this->belongsTo(Role::class);
    }

User model:

    public function surveys()
    {
        return $this->hasMany(Survey::class);
    }

Role model:

    public function users()
    {
        return $this->belongsToMany(User::class, 'role_user');
    }
    public function surveys()
    {
        return $this->belongsToMany(User::class, 'surveys');
    }
frankielee's avatar

@TheSolarwin

sorry i dont understand this "Because you are not using $user to load the surveys() relationship.".

If you are using this $user = auth()->user()->load('surveys.role);, you are using the $userto load the relationships. Therefore, the attributessurveyswill be added to the$user` variable. Thus, you can use this

foreach($user->sureys as $survey){
	//do anything you want here
	dump($survey,$survey->role);
}

I edited my database structure, please take a look at my DB diagram: https://ibb.co/jD1Fg0m

Just show the relationship between survey and role, that is enough.

As I said, you need to set the foreign key and local key.

Example:

return $this->hasOne(Role::class, 'role_id');

Learn the basics. https://laracasts.com/series/laravel-8-from-scratch

TheSolarwin's avatar

@frankielee hello on saturday :) Thanks I managed to get info about all surveys and their relationships with other tables, but that doesn't helped me to get resolve the first issue, please check the else statement in code bellow to understand where I am stuck. If i have to select all surveys for one group, there is no problem, but the problem is when I try to select surveys for current user and have to check the roles of user and then select only those surveys that belongs to these groups.

    public static function getSurveys(Request $request)
    {
        if(Role::find(1)->users()->where('id', auth()->id())->exists())     //role 1 is admin role (can see all surveys)
        {
            $surveys = Survey::with('role')->get();   //return all surveys
        }
        else
        {
            $surveys = Survey::where('user_id', '=', auth()->id())->orWhere("AND HERE IS THE FUN PART - select all surveys of ALL current user roles surveys"))->get(); //to get all user created surveys and all surveys that FK "role_id" is PK "id" in roles table.
        }

        return view('surveys',compact('surveys'));
    }

When I create new survey, I save value in Survey table column "role_id" based on other selected value. Model relatioships should be ok now.

User model:

    public function surveys()
    {
        return $this->hasMany(Survey::class);
    }

Survey model:

    public function role()
    {
        return $this->belongsTo(Role::class, 'role_id'); //works
    }

Roles model:

    public function users()
    {
        return $this->belongsToMany(User::class, 'role_user');
    }
    public function surveys()
    {
        return $this->hasMany(Survey::class, 'role_id');
    }

role_user model:

class role_user extends Model
{
    use HasFactory;
}

Edit: in php artisan tinker i tried:

App\Models\Roles::find(3)->surveys; //works - shows 3rd role surveys

App\Models\User::find(1)->surveys; //works - shows first users surveys

App\Models\User::find(auth()->id())->roles->surveys; //this doesn't work, but i need something like this

Edit 2: I found out how to get surveys for specific role (number 3 in example below), but how can I select surveys when user can be in multiple roles?

$surveys = Survey::with('role')->where('role_id', 3)->get();

frankielee's avatar
Level 29

@TheSolarwin So, the results have to base on the current user and the selected role?

Just add another condition?

        $surveys = Survey::where('user_id', auth()->id())->where('role_id',$role_id)->with('role')->get();

TheSolarwin's avatar

@frankielee thanks for your reply, results have to base on the current user (surveys who was created by current user) and current user roles. Table "Surveys" have FK "role_id". When user created survey, controller automatically add correct value in "role_id".

Your suggestion should work similar to my example below, but it can compare only for one role id. In my case, user can be a member of multiple roles.

 $surveys = Survey::with('role')->where('role_id', 3)->get();

I figured out how to get current user roles id's:

$surveys = Auth::user()->roles()->pluck('id')->toArray();

which returns:
array:4 [▼
  0 => 1
  1 => 25
  2 => 40
  3 => 3
]

I should get these arrays values in the where clause, but don't know how.

TheSolarwin's avatar

@frankielee thank you very much for patience and help during this problem :)

This is how i managed to show surveys based on user roles:

   	$roles = Auth::user()->roles()->pluck('id')->toArray();
        $surveys = Survey::with('role')->whereIn('role_id', $roles)->orWhere('user_id', '=', auth()->id())->get();   

Please or to participate in this conversation.