這篇文章主要給大家介紹了關於基於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,用户动态模块的开发就分享到这里,如果你有更高级的实现欢迎随时交流。
关于好友动态部分的实现,根据你的应用量级,以及好友关系的存储各有不同,大家自己集思广益即可,大部分都是先查好友关系再查动态,关联查询也可以,自己实现吧。
总结
以上是Laravel實作使用者動態模組開發的實例分享的詳細內容。更多資訊請關注PHP中文網其他相關文章!