index - mail::send laravel
Donde NO en la mesa pivote (7)
¿Qué hay de la izquierda unirse?
Suponiendo que las tablas son users
, items
y item_user
encuentran todos los items
no asociados con el usuario 123
:
DB::table(''items'')->leftJoin(
''item_user'', function ($join) {
$join->on(''items.id'', ''='', ''item_user.item_id'')
->where(''item_user.user_id'', ''='', 123);
})
->whereNull(''item_user.item_id'')
->get();
En Laravel podemos configurar relaciones como estas:
class User {
public function items()
{
return $this->belongsToMany(''Item'');
}
}
Permitiéndonos obtener todos los elementos en una tabla dinámica para un usuario:
Auth::user()->items();
Sin embargo, ¿qué pasa si quiero obtener lo opuesto a eso? Y obtenga todos los artículos que el usuario NO tiene todavía. Entonces NO en la tabla dinámica.
¿Hay una manera simple de hacer esto?
Mirando el código fuente de la clase Illuminate/Database/Eloquent/Builder
, tenemos dos métodos en Laravel que hacen esto: whereDoesntHave
(opuesto a whereHas
) y doesntHave
(opuesto a doesntHave
)
// SELECT * FROM users WHERE ((SELECT count(*) FROM roles WHERE user.role_id = roles.id AND id = 1) < 1) AND ...
User::whereDoesntHave(''Role'', function ($query) use($id) {
$query->whereId($id);
})
->get();
esto funciona correctamente para mi!
Para una simple relación "Donde no existe", usa esto:
User::doesntHave(''Role'')->get();
Lo siento, no entiendo inglés. Usé el traductor de google
No es tan simple, pero generalmente la forma más eficiente es usar una subconsulta.
$items = Item::whereNotIn(''id'', function ($query) use ($user_id)
{
$query->select(''item_id'')
->table(''item_user'')
->where(''user_id'', ''='', $user_id);
})
->get();
Si esto era algo que hacía a menudo, lo agregaría como un método de alcance al modelo del artículo.
class Item extends Eloquent {
public function scopeWhereNotRelatedToUser($query, $user_id)
{
$query->whereNotIn(''id'', function ($query) use ($user_id)
{
$query->select(''item_id'')
->table(''item_user'')
->where(''user_id'', ''='', $user_id);
});
}
}
Luego usa eso más tarde así.
$items = Item::whereNotRelatedToUser($user_id)->get();
Por simplicidad y simetría, podría crear un nuevo método en el modelo de Usuario:
// User model
public function availableItems()
{
$ids = /DB::table(''item_user'')->where(''user_id'', ''='', $this->id)->lists(''user_id'');
return /Item::whereNotIn(''id'', $ids)->get();
}
Para usar la llamada:
Auth::user()->availableItems();
Tal vez puedas usar:
DB::table(''users'')
->whereExists(function($query)
{
$query->select(DB::raw(1))
->from(''orders'')
->whereRaw(''orders.user_id = users.id'');
})
->get();
Terminó escribiendo un alcance para esto así:
public function scopeAvail($query)
{
return $query->join(''item_user'', ''items.id'', ''<>'', ''item_user.item_id'')->where(''item_user.user_id'', Auth::user()->id);
}
Y luego llama:
Items::avail()->get();
Funciona por ahora, pero un poco desordenado. Me gustaría ver algo con una palabra clave como not
:
Auth::user()->itemsNot();
Básicamente Eloquent está ejecutando la consulta anterior de todos modos, excepto con a =
lugar de a <>
.
esto debería funcionar para ti
$someuser = Auth::user();
$someusers_items = $someuser->related()->lists(''item_id'');
$all_items = Item::all()->lists(''id'');
$someuser_doesnt_have_items = array_diff($all_items, $someusers_items);