Laravel多态关系有很多

Edw*_*ard 9 php relationship has-many-through laravel

我有一个订阅者模型

// Subscriber Model

id
user_id
subscribable_id
subscribable_type

public function user()
{
    return $this->belongsTo('App\User');
}

public function subscribable()
{
    return $this->morphTo();
}
Run Code Online (Sandbox Code Playgroud)

和一个主题模型

// Topic Model

public function subscribers()
{
    return $this->morphMany('App\Subscriber', 'subscribable');
}
Run Code Online (Sandbox Code Playgroud)

我希望让所有用户通过订阅者模型,通知他们

通知::发送($ topic-> users,new Notification($ topic));

// Topic Model


public function users()
{
    return $this->hasManyThrough('App\User', 'App\Subscriber');
}
Run Code Online (Sandbox Code Playgroud)

有任何想法吗?

小智 19

// Topic Model

public function users()
{
    return $this->hasManyThrough('App\User', 'App\Subscriber', 'subscribable_id')->where('subscribable_type', array_search(static::class, Relation::morphMap()) ?: static::class);
}

多态hasManyThrough关系与其他任何关系相同,但是subscribable_type可以从Relation::morphMap()数组中检索,或者直接使用类名称添加约束.

  • 太好了,谢谢你,马特。为什么这不是公认的答案? (2认同)

Kha*_*leh 8

除了 Matt 的方法之外,以下代码也可能是另一种解决方案:

//Topic Model
public function users()
{
    return $this->belongsToMany(User::class, 'subscribers', 'subscribale_id', 'user_id')
        ->where('subscribale_type', static::class);
}
Run Code Online (Sandbox Code Playgroud)

以这种方式Subscriber被视为数据透视表,第二个参数是数据透视表的表名。

第三个参数是您在其上定义关系的模型的外键名称,而第四个参数是您要加入的模型的外键名称。在这里阅读更多。

考虑whereafter 子句belongsToMany仅过滤当前模型。


Mak*_*nov 6

你所追求的不是hasManyThrough,而是morphedByMany。

hasManyThrough当您有A一对多B、B一对多C,并且您想使用它A来获取多个C.

您拥有的是一个位于A和中间的多态数据透视表C。

// Topic Model

public function users()
{
    return $this->morphedByMany('App\User', 'subscribable', 'pivot/subscriber_table_name');
}
Run Code Online (Sandbox Code Playgroud)

文档:https : //laravel.com/docs/6.x/eloquent-relationships#many-to-many-polymorphic-relations


moh*_*hry 5

尝试这个包 https://github.com/staudenmeir/eloquent-has-many-deep

那么你可以这样使用它:

class Topic extends Model
{
    use \Staudenmeir\EloquentHasManyDeep\HasRelationships;
    public function users()
    {
        return $this->hasManyDeep(
            'App\User',
            ['App\Subscriber'],
            [null, ['subscribable_type', 'subscribable_id']]
        );
    }
}
Run Code Online (Sandbox Code Playgroud)