基于Laravel实现的用户动态模块开发

前言

相信大家都知道,几乎所有的社区应用都有用户动态这个部分,用户可以通过好友动态获能取到更多感兴趣的内容,从而提高社区活跃度和用户粘性。它的实现相对来讲比普通的内容发布要复杂一些,主要体现在内容多样性上。

为了解决这个问题,我们得把这些不同类型的内容抽象,提取共性,使用相同的结构来处理,开发起来就会简单很多。

概念抽象

用户动态,顾名思义,动态的产生,就是一系列事件的历史记录,所以首先关注“事件”这个名词,它有哪些属性:

  • 触发者,基于社区所有的事件几乎都是由用户触发的
  • 事件主体,事件的主体信息,例如“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,用户动态模块的开发就分享到这里,如果你有更高级的实现欢迎随时交流。

关于好友动态部分的实现,根据你的应用量级,以及好友关系的存储各有不同,大家自己集思广益即可,大部分都是先查好友关系再查动态,关联查询也可以,自己实现吧。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对我们的支持。

(0)

相关推荐

  • Laravel学习教程之广播模块详解

    前言 本文主要给大家介绍了关于Laravel广播模块的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍: 注意:本文是基于Laravel 5.4版本的路由模块代码进行分析书写: 简介 广播是指发送方发送一条消息,订阅频道的各个接收方都能及时收到消息:比如 A同学写了一篇文章,这时候 B同学在文章底下评论了,A同学在页面上是不用刷新就能收到提示有文章被评论了,这个本质上就是A同学收到了广播消息,这个广播消息是由B同学评论这个动作触发了发送广播消息: 在整个广播行为中,有一个重

  • Laravel学习教程之View模块详解

    前言 本文主要是给大家介绍了关于Laravel中View模块的相关资料,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. 本文是基于Laravel 5.4版本的路由模块代码进行分析书写: 文件结构 View模块的文件格局及功能如下图所示: 视图化呈现时的大概流程: 1.通过view()方法的调用,开始视图的呈现: 2.首先,查找视图文件: (1)依次遍历路径,如果文件名带命名空间(也就是::之前的部分),则采用命名空间对应注册的路径数组,否则采用全局路径数组(在Illuminat

  • Laravel学习教程之本地化模块

    前言 本文主要给大家介绍了关于Laravel本地化模块的相关内容,分享出来供大家参考学习,话不多说了,来一起看看详细的介绍吧. 本文是基于Laravel 5.4版本的本地化模块代码进行分析书写: 模块组成 下图展示了本地化模块各个文件的关系,并进行简要说明: TranslationServiceProvider 本地化模块的服务提供者,既是一个模块的入口,也是与IOC容器交互的中心:注册翻译器实例translation.loader,注册翻译管理实例translator,并声明延迟加载服务: T

  • Laravel中的Auth模块详解

    前言 本文主要给大家介绍的是关于Laravel中Auth模块的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. 本文是基于Laravel 5.4 版本的本地化模块代码进行分析书写: 模块组成 Auth模块从功能上分为用户认证和权限管理两个部分:从文件组成上,Illuminate\Auth\Passwords目录下是密码重置或忘记密码处理的小模块,Illuminate\Auth是负责用户认证和权限管理的模块,Illuminate\Foundation\Auth提供了登录.

  • Laravel学习教程之路由模块

    前言 本文主要给大家介绍的是关于Laravel路由模块的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. 备注:本文是基于Laravel 5.4版本的路由模块代码进行分析书写: 模块组成 下图展示了路由模块中各个文件的关系,并进行简要说明: 剖析 服务提供者 看Laravel模块,首先找ServiceProvider文件,这是模块与IOC容器交互的入口,从这个文件,可以看出该模块提供向系统提供了哪些服务: public function register() { //

  • 基于Laravel实现的用户动态模块开发

    前言 相信大家都知道,几乎所有的社区应用都有用户动态这个部分,用户可以通过好友动态获能取到更多感兴趣的内容,从而提高社区活跃度和用户粘性.它的实现相对来讲比普通的内容发布要复杂一些,主要体现在内容多样性上. 为了解决这个问题,我们得把这些不同类型的内容抽象,提取共性,使用相同的结构来处理,开发起来就会简单很多. 概念抽象 用户动态,顾名思义,动态的产生,就是一系列事件的历史记录,所以首先关注"事件"这个名词,它有哪些属性: 触发者,基于社区所有的事件几乎都是由用户触发的 事件主体,事件

  • 基于JSP的动态网站开发技术

    随着Web技术的发展和电子商务时代的到来,人们不再满足于建立各种静态地发布信息的网站,更多的时候需要能与用户进行交互,并能提供后台数据库的管理和控制等服务的动态网站. 动态网站开发技术 早期的动态网站开发技术使用的是CGI-BIN接口.开发人员编写与接口相关的单独的程序和基于Web的应用程序,后者通过Web服务器来调用前者.这种开发技术存在着严重的扩展性问题--每一个新的CGI程序要求在服务器上新增一个进程.如果多个用户并发地访问该程序,这些进程将耗尽该Web服务器所有的可用资源,直至其崩溃.

  • 基于Laravel Auth自定义接口API用户认证的实现方法

    基于 laravel 默认的 auth 实现 api 认证 现在微服务越来越流行了. 很多东西都拆分成独立的系统,各个系统之间没有直接的关系. 这样我们如果做用户认证肯定是统一的做一个独立的 用户认证 系统,而不是每个业务系统都要重新去写一遍用户认证相关的东西. 但是又遇到一个问题了. laravel 默认的auth 认证 是基于数据库做的,如果要微服务架构可怎么做呢? 实现代码如下: UserProvider 接口: // 通过唯一标示符获取认证模型 public function retri

  • Laravel 框架基于自带的用户系统实现登录注册及错误处理功能分析

    本文实例讲述了Laravel 框架基于自带的用户系统实现登录注册及错误处理功能.分享给大家供大家参考,具体如下: 一.默认 Laravel 不会自动帮你装上用户系统, 二.但是我们可以从默认首页的代码中看到,登录注册按钮被隐藏了 三.需要手动输入命令进行安装 php artisan make:auth 安装完成后重新刷新页面就可以到登录注册按钮了 四.可能遇到的问题 1. 当在注册页面点击注册时,一般会报如下错误,如果你没动过任何配置的话, SQLSTATE[HY000] [1045] Acce

  • Vue Element前端应用开发之用户管理模块的处理

    1.权限管理模块的设计 我们知道,权限管理一般都会涉及到用户.组织机构.角色,以及权限功能等方面的内容,ABP框架的基础内容也是涉及到这几方面的内容,其中它们之间的关系基本上是多对多的关系,它们的关系如下所示. 权限模块里面包含的一些主对象表和中间表,中间表主要用来存储两个对象之间的多对多关系,如角色包含多个用户,用户属于多个机构,机构包含多个角色等等. 结合ABP后端提供的接口,Vue前端我们要实现基础的用户.组织机构.角色.功能权限等内容的管理,以及维护它们之间的关系.Vue前端对于权限管理

  • 用python基于appium模块开发一个自动收取能量的小助手

    导语 ​ 昨天楼下买东西,超市老板居然让我加他支付宝好友???? 嗯哼!对啦,我也很疑惑来着!! 当时以为是方便下次买东西,哦吼也没多想,早上起来睁着我睡眼惺忪的熊猫眼,完了,我的能量都被偷完了! 对!今天木木子教大家种"树"!大家还记得蚂蚁森林叭,轻轻松松手机上就可以种树了! ​ 正文 本文是基于appium模块开发的自动收取能量的小助手! 参数配置如下: desired_caps = { "platformName": "Android",

  • 详解基于Angular4+ server render(服务端渲染)开发教程

    目标: 1.更好的 SEO,方便搜索爬虫抓取页面内容 2.更快的内容到达时间(time-to-content) 影响: 1.用户:比原来更快的看到渲染的页面,提升用户体验 2.开发人员:某些代码可能需要特殊处理,才能在服务器渲染应用程序中运行(window,document, navigator等) 安装: 1.nodejs 建议6+ 2.angular建议4.1+ 理论实现: 尽管这是一张来自vue官网服务器渲染的一张示意图,但是原理上和angular都是一样的,只是实现的代码不一致. SSR

  • Laravel 5.1 on SAE环境开发教程【附项目demo源码】

    本文实例讲述了Laravel 5.1 on SAE环境开发方法.分享给大家供大家参考,具体如下: Laravel-简洁.优雅的PHP开发框架,为 WEB 艺术家创造的 PHP 框架,如今正式移植到SAE环境. 由于Laravel 5.1相比于Laravel 4有很多的改动,不仅以目录结构更加清晰,而且功能也更丰富.但是Laravel官方还是没有原生支持SAE环境(估计永远不会支持),所以我就做了一个移植版本,可以很优雅的切换本地和SAE环境. 由于SAE的特殊性,那么这几个核心问题就必须要解决

  • JSP动态网页开发技术概述

    在动态web项目的开发中,经常需要动态生成HTML内容(如系统中的当前在线人数需要动态生成).如果使用Servlet实现HTML页面数据的统计,则需要使用大量的输出语句.同时,如果静态内容和动态内容混合在一起,那么也将导致程序非常臃肿.为了客服Servlet的这些缺点,Oracle(Sun)公司推出了JSP技术. 1.JSP概述 JSP(Java Server Pages)是建立在Servlet规范之上的动态网页开发技术,其实质是一个简化的Servlet.在JSP文件中,HTML和Java代码共

随机推荐