Laravel多态关系-警报系统

时间:2019-12-06 03:42:01

标签: php laravel eloquent

我有3个模型,UserAlertCategory

UserCategory之间的关系是多对多的。

AlertCategory之间的关系也是多对多的。

User应该只接收属于Alert所选择的Category的{​​{1}}。例如如果User具有 Travel Food 作为User,那么我只希望Category Travel < / strong>和食物显示在Alert中。

一旦User查看了User,对于特定的AlertAlert应该标记为“已读”。

目前我正在这样做:

User
Category.php

public function alerts()
{
    return $this->belongsToMany('App\Alert')->withTimestamps();
}

public function users()
{
    return $this->belongsToMany('App\User')->withTimestamps();
}
User.php

public function alerts()
{
   return $this->belongsToMany('App\Category')->withTimestamps();
}

public function categories()
{
   return $this->belongsToMany('App\Alert')->withTimestamps()->withPivot('read');
}

在当前的实现中,有3个数据透视表:Alert.php public function users() { return $this->belongsToMany('App\User')->withTimestamps()->withPivot('read'); } public function categories() { return $this->belongsToMany('App\Category')->withTimestamps(); } alert_categoryalert_usercategory_user表具有一个名为alert_user的额外字段,该字段基本上确定用户是否已阅读警报。即

read

此实现有很多缺陷,我什至认为它根本不起作用,因为新的alert_user table alert_id user_id read (holds 0 or 1) 将不会收到User在注册之前创建的Alert,如果{{1} }更改Alert,它将不会更新。当然,可以通过显式更新每个表来完成此操作,但是我不认为这是有效的,也不是体系结构。

我正在考虑将整个事物重构为多对多的多态关系。但是,如何确定Category是否已读取特定的User?我应该在哪里放置Alert字段?

您怎么看?我愿意接受任何想法。任何帮助将不胜感激。

编辑:

总结一下,我想我想做的是,它应该订阅read,而不是User订阅Alert。因此,实际上Category将接收相同User的所有Alert

2 个答案:

答案 0 :(得分:1)

如果您希望新注册的用户查看所选类别下的所有先前警报,则基本上是说已登录的用户应查看这些类别下的所有警报。

我认为将alertuser关联不会给您带来任何好处。如果有的话,它将给您带来额外的复杂性。

现在,如果要跟踪哪个users读取哪个alert,则可以使用alert_user表。基本上,您是在user读取alert时创建此关系的。 created_at会告诉您用户阅读alert的确切时间,因此也不需要read标志。

并且,要显示警报,您可以查询例如与登录用户没有关系记录的警报。您可以使用whereDoesntHave。例如,如下所示:

Alert::whereHas('categories', function($query) use ($category_id_array){

  $query->whereIn('category_id', $category_id_array);

})->whereDoesntHave('users', function($query) use ($user_id){

  $query->where('user_id', $user_id); //user_id is auth()->user()->id

})->get();

如果您只想显示推文而不排除已通过身份验证的用户:

Alert::whereHas('categories', function($query) use ($category_id_array){

  $query->whereIn('category_id', $category_id_array);

})->get();

答案 1 :(得分:0)

如果您希望选择一个用户并然后确定他是否有未读警报,则可以执行以下操作:

foreach($user->alerts as $alert){
 if($alert->read == 1){
  //do something with that particular alert
 }
}

如果要确定是否已读取特定警报,可以按以下方式进行搜索:

Alert::where('id', '=', $alert_id)->where('read', '=', 1)->first(); 
//will return alert or null