2016-05-20 14 views
5

Così ho User & Role modelli con molti-a-molti, ho 3 ruoli: super, admin e moderator con utenti 4 Diamo dice: John, Mike, James e Larry .Eloquente molti a molti selezionare User senza certi ruoli

John è un super, Mike ha admin e moderator ruoli, James è un admin e Larry è un moderator. Per gli utenti che visualizzano che non hanno certi ruoli Ho creato questo ambito:

public function scopeDoesntHaveRoles($query, $roles = [], $column = 'id') { 
    return $query->whereDoesntHave('roles')->orWhereHas('roles', function ($q) use ($roles, $column) { 
     $q->whereNotIn($column, $roles); 
    }); 
} 

Quando chiamo User::doesntHaveRoles([1])->lists('name', 'id') di convincere gli utenti che non hanno super ruolo, funziona e ritorni:

{"2":"Mike","3":"James","4":"Larry"} 

Ma , quando si cerca di elencare gli utenti che non hanno admin ruolo User::doesntHaveRoles([2])->lists('name', 'id'), sì James non viene mostrato lì, ma è apparso Mike, mentre lui è in realtà ha admin ruolo:

Penso che sia perché Mike ha anche il ruolo moderator, vede qualcosa di sbagliato nel mio campo di applicazione? o hai altre soluzioni?

Grazie

Edit: Ecco il mio schema di rotazione

Schema::create('user_roles', function (Blueprint $table) { 
    $table->integer('user_id')->unsigned(); 
    $table->integer('role_id')->unsigned(); 

    $table->primary([ 
     'user_id', 'role_id' 
    ]); 
}); 

User modello

public function roles() 
{ 
    return $this->belongsToMany(Role::class, 'user_roles'); 
} 

Role Modello

public function users() 
{ 
    return $this->belongsToMany(User::class, 'user_roles'); 
} 
+0

Può descrivere lo schema della tabella pivot tra il 'roles' e il' 'degli utenti tables.If si segue la convenzione si dovrebbe avere una colonna ROLE_ID su che vuoi chiamare il metodo 'whereNotIn'. – shempignon

+0

@shempignon È solo una tabella pivot di base, vedi post modificato. – Rifki

risposta

1

Vorrei utilizzare whereNotIn anziché whereDoesntHave.

Dato un Role memorizzato nella variabile $role è possibile ottenere tutti gli utenti che non dispongono di questo ruolo con:

/* @var Role $role */ 
User::whereNotIn(function('id', $query) use ($role) { 
    $query->select('user_id') 
     ->from('user_roles') 
     ->where('role_id', $role->id); 
}); 

La query interna restituirà tutti gli ID degli utenti che ha il ruolo dato. L'utilizzo di whereNotIn restituirà il gruppo di utenti opposto. verrà creata la query folowing:

select * 
from users 
where user_id not in (
    select user_id 
    from user_roles 
    where role_id = ? 
); 

Ora avendo un Collection di ruoli immagazzinate nella $roles è possibile ottenere tutti gli utenti che non hanno nulla di tutto ciò i ruoli con:

/* @var Collection|Role[] $roles */ 
User::whereNotIn(function('id', $query) use ($roles) { 
    $query->select('user_id') 
     ->from('user_roles') 
     ->whereIn('role_id', $roles->pluck('id'); 
}); 

Il SELECT interna restituisce gli ID di tutti gli utenti che hanno uno dei ruoli nella raccolta. Con whereNotIn otterrai di nuovo il risultato opposto. Puoi anche utilizzare una serie di ID ruolo anziché $roles->pluck('id').

Il costruttore creerà una query come

select * 
from users 
where user_id not in (
    select user_id 
    from user_roles 
    where role_id in (?, ?, ..) 
); 
+0

Finalmente ho trovato una soluzione brillante, grazie @PaulSpiegel è quello che sto cercando. – Rifki