Подтвердить что ты не робот

Где НЕ в сводной таблице

В Laravel мы можем настроить такие отношения:

class User {
    public function items()
    {
        return $this->belongsToMany('Item');
    }
}

Позволяет нам получить все элементы в сводной таблице для пользователя:

Auth::user()->items();

Однако, если я хочу получить противоположное. И получите все элементы, которые пользователь НЕ ДОЛЖЕН. Поэтому НЕ в сводной таблице.

Есть ли простой способ сделать это?

4b9b3361

Ответ 1

Для простоты и симметрии вы можете создать новый метод в модели User:

// User model
public function availableItems()
{
    $ids = \DB::table('item_user')->where('user_id', '=', $this->id)->lists('user_id');
    return \Item::whereNotIn('id', $ids)->get();
}

Чтобы использовать вызов:

Auth::user()->availableItems();

Ответ 2

Посмотрев исходный код класса Illuminate\Database\Eloquent\Builder, у нас есть два метода в Laravel: whereDoesntHave (напротив whereHas) и doesntHave (напротив has)

// 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();

это работает правильно для меня!

Для простого "Где не существует отношения" используйте это:

User::doesntHave('Role')->get();

Извините, не понимаю английский. Я использовал переводчик Google.

Ответ 3

Это не так просто, но обычно наиболее эффективным способом является использование подзапроса.

$items = Item::whereNotIn('id', function ($query) use ($user_id)
    {
        $query->select('item_id')
            ->table('item_user')
            ->where('user_id', '=', $user_id);
    })
    ->get();

Если бы это было то, что я часто делал, я бы добавил его как метод области к модели Item.

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);
        });
    }

}

Затем используйте это позже.

$items = Item::whereNotRelatedToUser($user_id)->get();

Ответ 4

Как насчет левого соединения?

Предполагая, что таблицы users, items и item_user найти все items, не связанные с пользователем 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();

Ответ 5

это должно работать для вас

$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); 

Ответ 6

Закончено создание области для этого так:

public function scopeAvail($query)
{
    return $query->join('item_user', 'items.id', '<>', 'item_user.item_id')->where('item_user.user_id', Auth::user()->id);
}

И затем вызовите:

Items::avail()->get();

Работает пока, но немного грязно. Хотелось бы увидеть что-то с ключевым словом вроде not:

Auth::user()->itemsNot();

В основном Eloquent запускает вышеуказанный запрос в любом случае, за исключением = вместо <>.

Ответ 7

Возможно, вы можете использовать:

DB::table('users')
        ->whereExists(function($query)
        {
            $query->select(DB::raw(1))
                  ->from('orders')
                  ->whereRaw('orders.user_id = users.id');
        })
        ->get();

Источник: http://laravel.com/docs/4.2/queries#advanced-wheres