欢迎加入QQ讨论群258996829
麦子学院 头像
苹果6袋
6
麦子学院

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

发布时间:2017-09-24 21:57  回复:0  查看:2480   最后回复:2017-09-24 21:57  

本文和大家分享的主要是基于Laravel的用户动态模块开发相关内容,一起来看看吧,希望对大家学习Laravel有所帮助。

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

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

  概念抽象

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

  1. 触发者 ,基于社区所有的事件几乎都是由用户触发的

  2. 事件主体 ,事件的主体信息,例如“xxx发布了文章中的 文章

  3. 事件属性 ,事件主体不同,所需要的附加信息也不同,比如事件类型。

  4. 发生时间 ,记录事件产生的时间,当然了在我们的数据库通常记录了所有数据产生的时间。

  我们将用户动态抽象成只有 4 个基础属性的结构,就比较容易实现了:

- description             事件描述

- causer_id 或者 user_id   事件触发者

- subject_id               主体 ID

- subject_type            主体类型

- properties              事件附加属性

- created_at              事件产生时间

  而主体部分就是 Laravel 里的 morph relation, 多态关联。

  怎么展示

  我们的动态展示需求通常有以下几种:

  1. 我的好友的动态

  2. 某个人的动态,通常是个人中心

  3. 全部动态,比如 Laravel China 首页的全部动态

  4. 动态搜索,比较少见

  我最近正在开发 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,用户动态模块的开发就分享到这里,如果你有更高级的实现欢迎随时交流。

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

 

 

来源:PHP / Laravel / 全栈

您还未登录,请先登录

热门帖子

最新帖子