基于Laravel实现的用户动态模块开发
发布时间 - 2026-01-11 03:21:08 点击率:次前言

相信大家都知道,几乎所有的社区应用都有用户动态这个部分,用户可以通过好友动态获能取到更多感兴趣的内容,从而提高社区活跃度和用户粘性。它的实现相对来讲比普通的内容发布要复杂一些,主要体现在内容多样性上。
为了解决这个问题,我们得把这些不同类型的内容抽象,提取共性,使用相同的结构来处理,开发起来就会简单很多。
概念抽象
用户动态,顾名思义,动态的产生,就是一系列事件的历史记录,所以首先关注“事件”这个名词,它有哪些属性:
- 触发者,基于社区所有的事件几乎都是由用户触发的
- 事件主体,事件的主体信息,例如“xxx发布了文章” 中的 “文章”。
- 事件属性,事件主体不同,所需要的附加信息也不同,比如事件类型。
- 发生时间,记录事件产生的时间,当然了在我们的数据库通常记录了所有数据产生的时间。
我们将用户动态抽象成只有 4 个基础属性的结构,就比较容易实现了:
- description 事件描述 - causer_id 或者 user_id 事件触发者 - subject_id 主体 ID - subject_type 主体类型 - properties 事件附加属性 - created_at 事件产生时间
而主体部分就是 Laravel 里的 morph relation, 多态关联。
怎么展示
我们的动态展示需求通常有以下几种:
- 我的好友的动态
- 某个人的动态,通常是个人中心
- 全部动态,比如 Laravel China 首页的全部动态
- 动态搜索,比较少见
我最近正在开发 EasyWeChat 新版网站,其中也有用户动态,举例:
xxx 发布了讨论 《请问大家怎么使用 xxx》 xxx 评论了 xxx 的话题 《请问大家怎么使用 xxx》 xxx 回复了 xxx 的评论 “我是按照文档上 ...” xxx 购买了 《微信开发:自定义菜单的使用》 xxx 关注了 xxx ...
你会发现,基本上每种动态的写法都不一样,所以我们还需要记录一个 “事件类型” ,比如 “关注”、 “发布”、“回复”、“购买”。
然后我们在 blade 或者其它模板引擎的使用中,就可以 switch ... case 写法,来应用不同的模板渲染这些样式,比如 blade 中,我的用法:
@switch($activity->properties['event'] ?? '')
@case('discussion.created')
...
@break
@case('comment.created')
...
@break
@endswitch
代码实现
前面我们已经讨论完了数据存储以及展示方面的设计,接着就是怎么实现,如果你比较勤劳,可以原生实现,毕竟上面的实现方法已经描述清晰,写点代码实现就搞定了,今天我要推荐的是使用 spatie/laravel-activitylog 来实现:
安装一直很简单对吧:
$ composer install spatie/laravel-activitylog -vvv
记录动态
activity()->log('Look, I logged something');
当然了这种记录没意义,几乎没有任何有用的信息,所以我们通常的用法应该是这样:
activity()
->performedOn($anEloquentModel)
->causedBy($user)
->withProperties(['customProperty' => 'customValue'])
->log('Look, I logged something');
$lastLoggedActivity = Activity::all()->last();
$lastLoggedActivity->subject; //returns an instance of an eloquent model
$lastLoggedActivity->causer; //returns an instance of your user model
$lastLoggedActivity->getExtraProperty('customProperty'); //returns 'customValue'
$lastLoggedActivity->description; //returns 'Look, I logged something'
方法介绍:
performedOn($model)设置事件主体,也就是 Eloquent Model 实例causedBy($user)设置事件触发者, User 实例withProperties($properties)上面我们概念里的事件属性withProperty($key, $value)事件属性的单个用法log($description)事件描述
比如,我们要记录一条,用户发布了讨论:
$discussion = App\Discussion::create([...]);
activity()->on($discussion)
->withProperty('event', 'discussion.created')
->log('发表了话题');
或者用户注册时,我要记录一条动态:
activity()->on($user)
->withProperty('event', 'user.created')
->log('加入 EasyWeChat');
你会发现我都没有设置触发者,因为这个模块如果你没设置触发者默认就是当前登录用户。
展示动态
展示动态就是根据条件从数据库拿出来,这里使用包提供的模型类:Spatie\Activitylog\Models\Activity
use Spatie\Activitylog\Models\Activity;
// 全部动态 $activities = Activity::all(); // 用户 ID 为 2 的动态 $activities = Activity::causedBy(User::find(2))->paginate(15); // 以文章 ID 为 13 为主体的动态 $activities = Activity::forSubject(Post::find(13))->paginate(15);
接着就是遍历展示就好了。
一些经验与技巧
设置一个专门的动态观察者类来记录动态
$ ./artisan make:listener UserActivitySubscriber
代码如下:
<?php
namespace App\Listeners;
class UserActivitySubscriber
{
protected $lisen = [
'eloquent.created: App\User' => 'onUserCreated',
'eloquent.created: App\Discussion' => 'onDiscussionCreated',
];
public function subscribe($events)
{
foreach ($this->lisen as $event => $listener) {
$events->lisen($event, __CLASS__.'@'.$listener);
}
}
public function onUserCreated($user)
{
activity()->on($user)
->withProperty('event', 'user.created')
->log('加入 EasyWeChat');
}
public function onDiscussionCreated($discussion)
{
activity()->on($discussion)
->withProperty('event', 'discussion.created')->log('发表了话题');
}
}
然后我们去注册这个订阅类:
在 App\Providers\EventServiceProvider 中 $subscribe 中注册这个订阅类:
/** * @var array */ protected $subscribe = [ \App\Listeners\UserActivitySubscriber::class, ];
上面我们利用了 Eloquent 模型事件来监听模型的变化,当各种模型事件创建的时候我们调用对应的方法来记录动态,所以实现起来非常的方便。
在事件属性里记录关键信息
看到上面记录动态的时候你可能会问,只存储了 ID,这种多态关联,查询的时候会压力很大,比如,我们要将动态显示为:
安小超 发布了文章 《自定义菜单的使用》
我们如果只是存储了文章的 id 与类型,我们还需要查询一次文章表,才能得到标题用于显示,这样一个动态列表的话,可能会几十条 SQL 了,的确是这样的,我的解决方案是这样的:
其实我们的用户动态是不要求 100% 精准的,所以,我如果在记录时把文章的标题一起存下来是不是就不用再查表了?其实就是,我们在动态列表需要展示的关键信息,比如标题这些一起用 withProperties 存起来,这样就一条 SQL 解决了动态列表问题。
这样的做法也有弊端,比如文章改了标题的时候,这里就不同步了,当然你也可以在文章修改时来改这个属性,不过我个人认为没有多大必要。毕竟动态就是记录了当时的情况,后来改标题了并没有什么问题。
OK,用户动态模块的开发就分享到这里,如果你有更高级的实现欢迎随时交流。
关于好友动态部分的实现,根据你的应用量级,以及好友关系的存储各有不同,大家自己集思广益即可,大部分都是先查好友关系再查动态,关联查询也可以,自己实现吧。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对的支持。
# laravel入门教程
# laravel
# 模块化
# 模块化开发
# Laravel实现用户注册和登录
# Laravel 5框架学习之用户认证
# Laravel重写用户登录简单示例
# laravel5.2实现区分前后台用户登录的方法
# Laravel框架用户登陆身份验证实现方法详解
# Laravel实现用户多字段认证的解决方法
# 通过修改Laravel Auth使用salt和password进行认证用户详解
# Laravel多用户认证系统示例详解
# 详解用vue.js和laravel实现微信授权登陆
# Laravel用户授权系统的使用方法示例
# 是这样
# 我要
# 发布了
# 自定义
# 还需要
# 你会发现
# 的是
# 都是
# 我是
# 就会
# 如果你
# 都有
# 也有
# 多态
# 都不
# 大家都
# 我都
# 就不
# 是由
# 集思广益
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
Laravel怎么判断请求类型_Laravel Request isMethod用法
googleplay官方入口在哪里_Google Play官方商店快速入口指南
Laravel如何使用Eloquent进行子查询
Laravel Sail是什么_基于Docker的Laravel本地开发环境Sail入门
如何确认建站备案号应放置的具体位置?
如何在阿里云部署织梦网站?
如何在服务器上配置二级域名建站?
Python文件操作最佳实践_稳定性说明【指导】
Laravel怎么实现API接口鉴权_Laravel Sanctum令牌生成与请求验证【教程】
Laravel的辅助函数有哪些_Laravel常用Helpers函数提高开发效率
Laravel怎么使用artisan命令缓存配置和视图
INTERNET浏览器怎样恢复关闭标签页_INTERNET浏览器标签恢复快捷键与方法【指南】
大型企业网站制作流程,做网站需要注册公司吗?
米侠浏览器网页图片不显示怎么办 米侠图片加载修复
Laravel如何与Vue.js集成_Laravel + Vue前后端分离项目搭建指南
详解ASP.NET 生成二维码实例(采用ThoughtWorks.QRCode和QrCode.Net两种方式)
网站优化排名时,需要考虑哪些问题呢?
Python结构化数据采集_字段抽取解析【教程】
Swift开发中switch语句值绑定模式
网站制作壁纸教程视频,电脑壁纸网站?
厦门模型网站设计制作公司,厦门航空飞机模型掉色怎么办?
Laravel如何实现全文搜索功能?(Scout和Algolia示例)
如何快速建站并高效导出源代码?
Laravel怎么防止CSRF攻击_Laravel CSRF保护中间件原理与实践
长沙企业网站制作哪家好,长沙水业集团官方网站?
Laravel如何使用Collections进行数据处理?(实用方法示例)
html5audio标签播放结束怎么触发事件_onended回调方法【教程】
Laravel如何优雅地处理服务层_在Laravel中使用Service层和Repository层
ChatGPT怎么生成Excel公式_ChatGPT公式生成方法【指南】
如何挑选高效建站主机与优质域名?
laravel怎么在请求结束后执行任务(Terminable Middleware)_laravel Terminable Middleware请求结束任务执行方法
微信h5制作网站有哪些,免费微信H5页面制作工具?
高配服务器限时抢购:企业级配置与回收服务一站式优惠方案
如何快速搭建高效WAP手机网站?
Java Adapter 适配器模式(类适配器,对象适配器)优缺点对比
使用Dockerfile构建java web环境
python中快速进行多个字符替换的方法小结
香港服务器建站指南:外贸独立站搭建与跨境电商配置流程
标题:Vue + Vuex + JWT 身份认证的正确实践与常见误区解析
HTML 中动态设置元素 name 属性的正确语法详解
为什么要用作用域操作符_php中访问类常量与静态属性的优势【解答】
如何在云主机快速搭建网站站点?
如何在 React 中条件性地遍历数组并渲染元素
iOS UIView常见属性方法小结
Laravel怎么集成Vue.js_Laravel Mix配置Vue开发环境
Android okhttputils现在进度显示实例代码
实现点击下箭头变上箭头来回切换的两种方法【推荐】
Python进程池调度策略_任务分发说明【指导】
如何在IIS7上新建站点并设置安全权限?
如何快速重置建站主机并恢复默认配置?

