1

I'm trying to filter the users from a specific user group in a component in PHP. First, I'm search for a specific user based on a keyword, next I want to test if this user belongs to one specific group 'mygroupcode'. Ideally these two statements should be combined.

I've tried the following:

public function onSelect() {
    $s2_opts = [];
    foreach(User::where('surname', 'LIKE', '%'.Input::get('q').'%')->orWhere('name', 'LIKE', '%'.Input::get('q').'%')->get() as $user) {
        if($user->groups()->whereName('mygroupcode')->exists()) {
            array_push($s2_opts, array('id' => $user->id, 'text' => $user->name . ' ' . $user->surname));
        }
    }
    return json_encode($s2_opts);
}

This throws a MySQL-error. Something like table mydb.groups not found... In the database, it should look for user_groups instead.

Also, I've tried:

public function onSelect() {
    $s2_opts = [];
    foreach(User::where('surname', 'LIKE', '%'.Input::get('q').'%')->orWhere('name', 'LIKE', '%'.Input::get('q').'%')->get() as $user) {
        if(in_array('mygroupcode',array_keys($user->groups))) {
            array_push($s2_opts, array('id' => $user->id, 'text' => $user->name . ' ' . $user->surname));
        }
    }
    return json_encode($s2_opts);
}

This also yields a MySQL error. Similar, also about table groups not being found.

Also, I've noticed there's a method called inGroup(), but this yields the same error...

public function onSelect() {
    $s2_opts = [];
    foreach(User::where('surname', 'LIKE', '%'.Input::get('q').'%')->orWhere('name', 'LIKE', '%'.Input::get('q').'%')->get() as $user) {
        if($user->inGroup('mygroupcode')) {
            array_push($s2_opts, array('id' => $user->id, 'text' => $user->name . ' ' . $user->surname));
        }
    }
    return json_encode($s2_opts);
}

What am I doing wrong? Thanks in advance for your time.

Please note the following related questions. They are regarding backend user lists, I am looking to filter down frontend users.

chocolata
  • 3,258
  • 5
  • 31
  • 60

2 Answers2

2

If you look at the InGroup function the param is not a string (code) but an Object :

/**
 * See if the user is in the given group.
 * @param Group $group
 * @return bool
 */
public function inGroup($group)
{
    foreach ($this->getGroups() as $_group) {
        if ($_group->getKey() == $group->getKey()) {  
            return true;
        }
    }

    return false;
}

You can add to your UserGroup model a method let's say :

const GROUP_ADMIN     =   'admin'; // admin is the group unique code

public static function getAdminGroup()
 {
    return self::where('code', self::GROUP_ADMIN)->first() ;
 }

Then you can use this method to check if the User is in the Group

public function onSelect() {

    $q = Input('q', false );

    if (!empty ($q)) {

       $users = User::searchWhere( $q , 'surname' )
                      ->searchWhere( $q , 'name' )
                      ->get();

        if ( count ($users) ) {

            $s2_opts = [];

            $users->each( function( $user ) {
                if( $user->inGroup( UserGroupModel::getAdminGroup() )) {
                    // User is in Group... Push to Array
                }
            });

             return json_encode($s2_opts);

        } else {
            // No users found...
        }                 
    }

}

Also have a look at the filter method you can return a filtered collection based on some condition

$filteredUsers = $users->filter(function ( $user ) {
    return $user->inGroup( UserGroupModel::getAdminGroup() ) ;
});
Raja Khoury
  • 3,015
  • 1
  • 20
  • 19
  • Thanks Raja. This looks very elegant. I'm guessing the public static function getAdminGroup() should be defined in the Plugin.php file of my component, yes? Within `class Plugin extends PluginBase {}`? – chocolata Aug 14 '17 at 08:15
  • No the static method should be defined in the Model in this case the User Group model. Bear in mind if you add it there then update the user plugin you will loose the changes, so read the docs how to extend a plugin model ,then you can extend it from your own plugin safetly. In case you don't wish to update the user plugin in the future then I assume it's fine to just add it there. – Raja Khoury Aug 14 '17 at 15:53
  • Also your code looks fine you can stick to that just the problem was that the inGroup method expects an instance of the Model so add : $group=UserGroup::whereCode('mycode')->first(); then pass $group as param instead of the code: $user->inGroup($group).. – Raja Khoury Aug 14 '17 at 16:00
  • 1
    Thanks Raja, this seems to work. I still need to figure some details out, but the inGroup method now seems to yield results. October rocks! – chocolata Aug 15 '17 at 07:53
0

I managed to get a working solution by relying on the query builder. I doubt that it is the optimal solution, but for now it's working. If anyone has a better solution, please let me know:

public function onSelect() {
    $s2_opts = [];
    foreach(User::select('users.id', 'users.surname', 'users.name')
                ->join('users_groups', 'users.id', '=', 'users_groups.user_id')
                ->join('user_groups', 'users_groups.user_group_id', '=', 'user_groups.id')
                ->where('user_groups.code','mygroupcode')
                ->where(function ($query) {
                    $query->where('users.surname', 'LIKE', '%'.Input::get('q').'%')->orWhere('users.name', 'LIKE', '%'.Input::get('q').'%');
                })
                ->groupBy('users.id')
                ->get() as $user) {
        array_push($s2_opts, array('id' => $user->id, 'text' => $user->name . ' ' . $user->surname));
    }

    return json_encode($s2_opts);
}
chocolata
  • 3,258
  • 5
  • 31
  • 60