我有3个模型,User
,Alert
和Category
。
User
和Category
之间的关系是多对多的。
Alert
和Category
之间的关系也是多对多的。
User
应该只接收属于Alert
所选择的Category
的{{1}}。例如如果User
具有 Travel 和 Food 作为User
,那么我只希望Category
与 Travel < / strong>和食物显示在Alert
中。
一旦User
查看了User
,对于特定的Alert
,Alert
应该标记为“已读”。
目前我正在这样做:
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_category
和alert_user
。 category_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
。
答案 0 :(得分:1)
如果您希望新注册的用户查看所选类别下的所有先前警报,则基本上是说已登录的用户应查看这些类别下的所有警报。
我认为将alert
与user
关联不会给您带来任何好处。如果有的话,它将给您带来额外的复杂性。
现在,如果要跟踪哪个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