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

更新:2017-10-25    编辑:盘宽网    来源:GeGuai    人气:加载中...    字号:|

标签:实现  用户  动态  Laravel  开发  基于  百度搜索

前言

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

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

概念抽象

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

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

- description 事件描述 - causer_id 或者 user_id 事件触发者 - subject_id 主体 ID - subject_type 主体类型 - properties 事件附加属性 - created_at 事件产生光阴

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

怎么展示

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

最近正在开发 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'

法子介绍:

比如,我们要记载一条,用户发布了讨论:

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

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

总结


评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)

站点导航

您可能在找这些