Web News表设计
以下基于 tp news table 来分析.
1-1 1-many many-many
关系数据库最重要的几个关系,看如何运用:
表:
news_t:
id, title,content. cate_id, user_id
comments_t:
id, body, commentable_type, commentable_id...
cates_t:
id, name...
users_t:
id, email, name...
pined_t:
id, news_id, comments_id,status,user_id(冗余),reply_user(冗余)
结合 laravel-query-bulider 的关系描述:
1 news hasmany(morphmany) comments;
1 news belongsto 1 cate;
1 news belongsto 1 user;
1 news belongstomany pined;
关系的本质都是 sqld 的 join 查询,并没有什么特殊的.
最后 1 个可能不好理解.
描述多对多
的示例是posts-tags
,这个是符合的.但上面的news-pined_comments
关系实质不是多对多,1 个 news 可能有多条置顶评论,但 1 条置顶评论不应该出现在多个 news 里.
为啥又可以的?记住:多对多的实质是中间表
,pined 就是中间表.
多对多更多是sql语法上的抽象,不能完全理解为关系上的抽象
.
news--pined---comments
查找某个新闻(id=2)下的置顶(status=1)评论
select c.* from comments_t as cl inner join pined_t as p on (p.comment_id= c.id)
inner join news_t as n on (p.status=1 and n.id = p.news_id and n.id=2);
其实最简单的做法,就是直接在 comments table 增加字段 status 表示是否置顶.
但 tp 这里的 pined 不但有评论置顶,还是 news 置顶,feed 置顶..就是是个中间表无误了.
如果还要设计啥精选
评论,思路都是一样的.
除了这个多对多
,个人觉得 tp 里的这个关系设计不够laravel
,分类没有采用morph
,而是用的 channel 字段自己判断 type:
public function pinnedComments() {
return $this->belongsToMany(Comment::class, 'news_pinneds', 'target', 'raw')->where('channel', 'news:comment');
}
实际这个置顶表耦合了太多内容,不规范的地方比如,还是用 join 试图查找某个分类下的所有的置顶文章.
->join('news_pinneds', function ($join) use ($datetime) {
return $join->on('news_pinneds.target', '=', 'news.id')->where('channel', 'news')->where('expires_at', '>', $datetime);
})
有没有足够laravel-eloquentnic
的方法?
///in cate model
public funtion pined_news() {
return $this->belongstoMany(News::class,'pinned',
'target','cate_id');
}
其他的
还有有几个 table 和关系是通过 trait 封装的,包括:
# 被收藏
news_collections:
id, news_id, user_id
# 被点赞
likes:
id,user_id,likeable_type, likable_id
关系描述是:
# 被多人收藏(1篇文章允许被多人收藏,1人允许点赞多篇文章)
1 news belongstomany many user_id
# 被多人点赞(点赞可分类型,所以是morph)
1 news morphmany many user_id