首頁  >  文章  >  後端開發  >  Laravel實作使用者動態模組開發的實例分享

Laravel實作使用者動態模組開發的實例分享

黄舟
黄舟原創
2017-09-23 09:33:521244瀏覽

這篇文章主要給大家介紹了關於基於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 = [
  &#39;eloquent.created: App\User&#39; => &#39;onUserCreated&#39;,
  &#39;eloquent.created: App\Discussion&#39; => &#39;onDiscussionCreated&#39;,
 ];

 public function subscribe($events)
 {
  foreach ($this->lisen as $event => $listener) {
   $events->lisen($event, __CLASS__.&#39;@&#39;.$listener);
  }
 }

 public function onUserCreated($user)
 {
  activity()->on($user)
   ->withProperty(&#39;event&#39;, &#39;user.created&#39;)
   ->log(&#39;加入 EasyWeChat&#39;);
 }

 public function onDiscussionCreated($discussion)
 {
  activity()->on($discussion)
    ->withProperty(&#39;event&#39;, &#39;discussion.created&#39;)->log(&#39;发表了话题&#39;);
 }
}

然後我們去註冊這個訂閱類別:

在App\Providers\EventServiceProvider 中$subscribe 中註冊這個訂閱類別:


#
/**
 * @var array
 */
protected $subscribe = [
 \App\Listeners\UserActivitySubscriber::class,
];

上面我们利用了 Eloquent 模型事件来监听模型的变化,当各种模型事件创建的时候我们调用对应的方法来记录动态,所以实现起来非常的方便。

在事件属性里记录关键信息

看到上面记录动态的时候你可能会问,只存储了 ID,这种多态关联,查询的时候会压力很大,比如,我们要将动态显示为:

安小超 发布了文章 《自定义菜单的使用》

我们如果只是存储了文章的 id 与类型,我们还需要查询一次文章表,才能得到标题用于显示,这样一个动态列表的话,可能会几十条 SQL 了,的确是这样的,我的解决方案是这样的:

其实我们的用户动态是不要求 100% 精准的,所以,我如果在记录时把文章的标题一起存下来是不是就不用再查表了?其实就是,我们在动态列表需要展示的关键信息,比如标题这些一起用 withProperties 存起来,这样就一条 SQL 解决了动态列表问题。

这样的做法也有弊端,比如文章改了标题的时候,这里就不同步了,当然你也可以在文章修改时来改这个属性,不过我个人认为没有多大必要。毕竟动态就是记录了当时的情况,后来改标题了并没有什么问题。

OK,用户动态模块的开发就分享到这里,如果你有更高级的实现欢迎随时交流。

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

总结

以上是Laravel實作使用者動態模組開發的實例分享的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn