laravel 数据透视表中的“非”位置

wvt8vs2t  于 2023-01-14  发布在  其他
关注(0)|答案(8)|浏览(139)

在Laravel中,我们可以这样设置关系:

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

允许我们为用户获取透视表中的所有项:

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

然而,如果我想得到相反的结果呢?得到用户还没有的所有项目。所以不在透视表中。
有没有简单的方法可以做到这一点?

sd2nnvve

sd2nnvve1#

查看类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();

这对我来说是正确的!
对于简单的“Where not exists relationship”,请使用以下命令:

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

对不起,我不懂英语,我用的是谷歌翻译。

nkcskrwz

nkcskrwz2#

为了简单和对称,您可以在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();
}

要使用call:

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

4ktjp1zp3#

这并不简单,但通常最有效的方法是使用子查询。

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

xn1cxnb44#

左连接怎么样?
假设表是usersitemsitem_user,则查找与用户123不关联的所有items

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

w41d8nur5#

这应该对你有用

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

r7xajy2e6#

最后写了这样一个作用域:

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无论如何都会运行上面的查询,只是用=代替了<>

hujrc8aj

hujrc8aj7#

也许你可以使用:

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

图片来源:www.example.comhttp://laravel.com/docs/4.2/queries#advanced-wheres

g52tjvyc

g52tjvyc8#

$items = $this->item->whereDoesntHave('users')->get();

相关问题