Php 查询对象之间的间接关系

Php 查询对象之间的间接关系,php,laravel,eloquent,Php,Laravel,Eloquent,使用Laravel 5.6,假设我有以下数据库表: networks users vlans -------- ----- ----- id id id network_id network_id vlan_id 这些关系: class Network extends Model { public function users() { return $this->

使用Laravel 5.6,假设我有以下数据库表:

networks   users        vlans
--------   -----        -----
id         id           id
           network_id   network_id
           vlan_id
这些关系:

class Network extends Model {
    public function users() { return $this->hasMany("User"); }
    public function vlans() { return $this->hasMany("Vlan"); }
}

class User extends Model {
    public function network() { return $this->belongsTo("Network"); }
    public function vlan()    { return $this->belongsTo("Vlan"); }
}

class Vlan extends Model {
    public function network() { return $this->belongsTo("Network"); }
    public function user()    { return $this->hasOne("User"); }
}
我的问题是:给定
网络
ID,是否有一种简单的方法来确定哪些
Vlan
对象是而不是分配给
用户


这是一个非常早期的阶段(我对拉雷维尔很陌生),所以如果我把关系搞砸了,我会毫不犹豫地重新开始。我考虑过改变一些东西,以便
vlans
表具有
user\u id
外键,但这似乎是倒退。(这会给我留下一个相反的问题:如何找到所有没有
Vlan
分配的
User
对象!)

您可以在Vlan模型中添加一个作用域:

public function scopeNotAssigned($query, $id)
{
    return $query->whereNotIn(
        'id',
        User::where('network_id', $id)->select('vlan_id')->get()->pluck('vlan_id')->toArray()
    );
}
public function user()
{
    return $this->hasOne('App\User');
}
然后假设您有一个网络:

$network = \App\Network::first();
您可以如下方式检索网络中未分配的VLAN:

$vlans = \App\Vlan::notAssigned($network->id)->get();

否则,您还可以在Vlan模型中添加与用户的关系:

public function scopeNotAssigned($query, $id)
{
    return $query->whereNotIn(
        'id',
        User::where('network_id', $id)->select('vlan_id')->get()->pluck('vlan_id')->toArray()
    );
}
public function user()
{
    return $this->hasOne('App\User');
}
然后您可以使用
whereDoesntHave
功能:

$vlans = Vlan::whereDoesntHave('users', function ($query) use ($network) {
    return $query->where('network_id', $network->id);
})->get();

这是一种多对多的关系吗?如中所示,一个vlan可以属于多个用户,而一个用户可以有多个vlan?您只能将一个vlan分配给一个用户。@ChinLeung不,这是一对一;VLAN是用户专用的,用户只能有一个。你看到了吗?这可能会有帮助: