给帖子发表回复后更新帖子回复总数的5种方式
我们常常有类似这样的需求,比如一个论坛,有帖子topic,有回复comment,在帖子下发布回复后我们常常需要在帖子表topic的comment_count字段+1,这样我们就可以在读取帖子详情时直接知道这个帖子有多少回复,而不需要对comment表做count查询,这样带来的好处不仅是方便,而且性能更好,比如帖子列表页一次性列出50条帖子,如果分别做50次count查询显然不现实, 在次总结5种实现方式。
topicID | 标题 | 回帖数 | 浏览数 |
---|---|---|---|
1003 | 消息不可靠 | 12 | 203 |
1001 | 站长是基佬 | 60 | 856 |
在 Laravel 中,如果你想要实现在添加 comment
表记录时,自动更新对应 topic
表的 comment_count
列,可以采用以下几种方法:
1. 使用模型事件(Model Events)
在 Comment
模型中使用 created
事件来更新 topic
的 comment_count
。
class Comment extends Model
{
public static function boot()
{
parent::boot();
static::created(function ($comment) {
// 这里的$comment->topic是假设模型有关联
// 这里直接+1, 也可以做count
// 并发会让这种方式不一定精确,有精确需求的请加锁或者考虑其他方式
// 有删除帖子功能别忘记一样的操作
$topic = $comment->topic;
$topic->comment_count++;
$topic->save();
});
}
}
2. 使用本地数据库触发器(Database Trigger)
在数据库层面创建一个触发器,当向 comment
表插入新记录后自动更新 topic
表的 comment_count
。
DELIMITER //
CREATE TRIGGER after_comment_insert
AFTER INSERT ON comment
FOR EACH ROW
BEGIN
UPDATE topic
SET comment_count = comment_count + 1
WHERE id = NEW.topic_id;
END; //
DELIMITER ;
3. 使用 Laravel 的监听器(Listeners)
创建一个事件监听器,当 Comment
被创建后,监听器将处理更新 topic
的逻辑。
// Event: CommentCreated
class CommentCreated
{
public $comment;
public function __construct(Comment $comment)
{
$this->comment = $comment;
}
}
// Listener: UpdateTopicCount
class UpdateTopicCount
{
public function handle(CommentCreated $event)
{
// 同方案1一样,想精确得加锁
$event->comment->topic->comment_count++;
$event->comment->topic->save();
}
}
然后在 Comment
模型的 created
事件中触发这个事件:
use App\Events\CommentCreated;
static::created(function ($comment) {
event(new CommentCreated($comment));
});
4. 利用数据库的级联更新
如果你使用的是支持外键级联操作的数据库系统(如 PostgreSQL),可以设置外键约束来自动更新 comment_count
。
ALTER TABLE comment
ADD CONSTRAINT comment_topic_id_fkey
FOREIGN KEY (topic_id)
REFERENCES topic(id)
ON INSERT UPDATE topic.comment_count;
请注意,并非所有的数据库系统都支持这种操作。
5. 手动更新
虽然不是自动的,但你也可以选择在添加评论后手动更新 topic
的 comment_count
。
复制
$comment = new Comment();
// ... 填充 $comment 数据并保存
$topic = Topic::find($comment->topic_id);
$topic->comment_count++;
$topic->save();
本作品采用《CC 协议》,转载必须注明作者和本文链接
所以这几种性能如何呢~
总结呢 :see_no_evil:
所以这种基本操作使用过程真的合理么?这点性能可以忽略不计,但是搞不好这真的就成了祖传逻辑了。
还有一个
observer
的方式,其实等同于event
和listener
方式,本质都是观察者模式。Laravel Observer
这几种方式,主要就是数据库层面与代码层面实现的区别: