為你的論壇系統新增一個『提及』功能

pigzzz發表於2019-07-15

在論壇系統中,提及使用者 是一個很常見的功能,也就是我們常說的@

例如:在learnku的回帖功能中我們可以看到,鍵入@會自動輸出你已關注的使用者列表,回帖成功後,被提及使用者將受到一條通知

為你的論壇系統新增一個『提及』功能
回帖完成後,被@使用者將會收到一條訊息通知。今天,我們將為larabbs來新增這一功能

修改資料模型

我們可以使用正規表示式,來匹配使用者回覆內容中提及的一個或多個使用者。我們需要修改下 Reply 模型。
修改檔案為以下:

app/Models/Reply.php

<?php

namespace App\Models;

class Reply extends Model
{
    .
    .
    .
    public function mentionedUsers()
    {
        preg_match_all('/@([\w\-]+)/', $this->content, $matches);
        return $matches[1];
    }
}

生成通知類

$ php artisan make:notification UserMentioned

修改檔案為以下:

app/Notifications/UserMentioned.php

<?php

namespace App\Notifications;

use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use App\Models\Reply;

class UserMentioned extends Notification
{
    use Queueable;

    public $reply;

    public function __construct(Reply $reply)
    {
        // 注入回覆實體,方便 toDatabase 方法中的使用
        $this->reply = $reply;
    }

    public function via($notifiable)
    {
        // 開啟通知的頻道
        return ['database'];
    }

    public function toDatabase($notifiable)
    {
        $topic = $this->reply->topic;
        $link =  $topic->link(['#reply' . $this->reply->id]);

        // 存入資料庫裡的資料
        return [
            'reply_id' => $this->reply->id,
            'reply_content' => $this->reply->content,
            'user_id' => $this->reply->user->id,
            'user_name' => $this->reply->user->name,
            'user_avatar' => $this->reply->user->avatar,
            'topic_link' => $link,
            'topic_id' => $topic->id,
            'topic_title' => $topic->title,
        ];
    }
}

觸發通知

我們希望當使用者回覆主題後,通知到被提及使用者。故觸發通知的時機是:『回覆釋出成功後』,在模型監控器裡,我們可以在 created 方法裡實現此部分程式碼,修改 created() 方法為以下:

app/Observers/ReplyObserver.php

<?php
.
.
.
use App\Models\User;
use App\Notifications\UserMentioned;

class ReplyObserver
{
    public function created(Reply $reply)
    {
        .
        .
        .
        // 通知被提及使用者
        User::whereIn('name', $reply->mentionedUsers())
            ->get()
            ->each(function ($user) use ($reply) {
                $user->notify(new UserMentioned($reply));
            });
    }

    .
    .
    .
}

建立通知模板

建立此檔案:

resources/views/notifications/types/_user_mentioned.blade.php

<li class="media @if ( ! $loop->last) border-bottom @endif">
  <div class="media-left">
    <a href="{{ route('users.show', $notification->data['user_id']) }}">
      <img class="media-object img-thumbnail mr-3" alt="{{ $notification->data['user_name'] }}" src="{{ $notification->data['user_avatar'] }}" style="width:48px;height:48px;" />
    </a>
  </div>

  <div class="media-body">
    <div class="media-heading mt-0 mb-1 text-secondary">
      <a href="{{ route('users.show', $notification->data['user_id']) }}">{{ $notification->data['user_name'] }}</a>
      在
      <a href="{{ $notification->data['topic_link'] }}">{{ $notification->data['topic_title'] }}</a>
      的評論中提及了你

      <span class="meta float-right" title="{{ $notification->created_at }}">
        <i class="far fa-clock"></i>
        {{ $notification->created_at->diffForHumans() }}
      </span>
    </div>
    <div class="reply-content">
      {!! $notification->data['reply_content'] !!}
    </div>
  </div>
</li>

至此,提及使用者 功能開發完畢

相關文章