web-dev-qa-db-ja.com

ピボットテーブルにない場所

Laravelでは、次のように関係を設定できます。

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

ユーザーがピボットテーブル内のすべてのアイテムを取得できるようにします。

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

しかし、それとは逆のことをしたい場合はどうでしょうそして、ユーザーがまだ持っていないすべてのアイテムを取得します。したがって、ピボットテーブルにはありません。

これを行う簡単な方法はありますか?

30
Rob

単純さと対称性のために、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();
13
Makita

クラスのソースコードを見るIlluminate\Database\Eloquent\Builder、これを行うLaravelには2つのメソッドがあります:whereDoesntHavewhereHasの反対)とdoesntHavehas

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

英語が理解できません。私はグーグル翻訳機を使いました。

45
Wallace Maxters

それほど単純ではありませんが、通常、最も効率的な方法はサブクエリを使用することです。

$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();
6
Collin James

左結合はどうですか?

テーブルがusersitemsitem_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();
1
mp31415

そのため、次のようなスコープを作成することになりました。

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は上記のクエリを実行していますが、=の代わりに<>

0
Rob

多分あなたは使うことができます:

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

0
Turcko007

これはあなたのために働くはずです

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