Laravel——消息通知

5,986 阅读2分钟

有的时候,在做一些业务的时候,可能会遇到这么个需求。那就是,别人评论了你的某个东西,或者是关注你,再或者是收藏了你的文章,那么作者,应该是需要被通知一下,以展现一下作者该有的成果,也可以满足一下作者小小的虚荣心嘛。

Laravel其实内部就自带消息通知的。接下来就看看是怎么使用的。

创建消息notifications表,并且给用户增添字段notification_count

消息表,毋庸置疑是给用来记录消息内容的——是谁在哪篇文章哪个时间评论了哪个作者的,对吧。那么notifiation_count是记录用户有几条消息是未读的对吧。 下面操作。

  1. 跑命令自动生成notification迁移表命令
php artisan notification:table

会生成 database/migrations/{$timestamp}_create_notifications_table.php 迁移文件,再执行下面命令将表添加到数据库里。

php artisan migrate
  1. users表添加字段,用来跟踪用户未读的消息,到时候就可以判断是否大于0,来是否显示出来。跑命令
php artisan make:migration add_notification_count_to_users_table --table=users

这样在databasemigration下就会生成这个迁移文件。进行添加想要的字段

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class AddNotificationCountToUsersTable extends Migration
{
    public function up()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->integer('notification_count')->unsigned()->default(0);
        });
    }

    public function down()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->dropColumn('notification_count');
        });
    }
}

应用到数据库修改,跑迁移命令,那么users表里就会增加一条notification_count字段

php artisan migrate

生成通知类

  1. 首先,跑以下命令自动在app\Notifications里创建通知类。
php artisan make:notification TopicReplied
  1. 修改文件以下 app/Notifications/TopicReplied.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 TopicReplied extends Notification
{
    use Queueable;

    public $reply;

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

    public function via($notifiable)
    {
        // 开启通知的频道,因为是涉及数据库的通知,这里写database
        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,
        ];
    }
}

最后的toDatabase方法接收$notifiable的实例参数并返回一个数组。 返回的数组会以json格式存储到notification表里的data字段中。

重写User模型的notify方法。

默认的User模型里用了trait——Notifiable的,它包含着一个可以用来发通知的一个方法notify(),该方法接收一个通知的实例作为参数。虽然notify()方法已经封装的很方便了,但是我们想要每次调用的时候,让字段notification_count自动加一,这样就能跟踪用户未读通知了。

打开 app/Models/User.php

<?php
.
.
.
use Auth
class User extends Authenticatable {
    use notifiable {
        notify as protected laravelNotify;
    }
    
    public function notify($instance) {
        // 如果不是当前用户,就不必通知了
        if($this->id == Auth::id()) {
            return;
        }
        $this->increment('notification_count');
        $this->laravelNotify($instance);
    }
}

这里就对notify方法进行了巧妙的重写,这样,每次调用的时候,notification_count会自动 + 1。

触发通知

那么触发的话,肯定就是在比如别的用户评论了作者的某篇文章,也就是replyController里进行store方法存储的时候,触发。

    public function store(Reply $reply) 
    {
        .
        .
        $topic = $reply->topic;
        $topic->increment('reply_count', 1);
        
        // 通知作者话题被回复了
        $topic->user->notify(new TopicReplied($reply));
    }

将通知的数据进行获取并渲染

  1. 编写消息通知的路由
Route::resource('notifications', 'NotificationsController', ['only' => ['index']]);
  1. 新建NotificationsController的控制器,为了方便对通知的管理,这里就新建控制器,跑命令自动生成。
php artisan make:controller NotificatioonsController
  1. 在控制器里写逻辑代码
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Auth;

class NotificationsController extends Controller
{
    public function __construct()
    {
        $this->middleware('auth');
    }

    public function index()
    {
        // 获取登录用户的所有通知
        $notifications = Auth::user()->notifications()->paginate(20);
        return view('notifications.index', compact('notifications'));
    }
}
  1. 这里面值得注意的是,$notifications里循环出来的数据,渲染的时候需要加上$notification->data然后在后面继续跟上想要的数据。
<div class="infos">
        <div class="media-heading">
            <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 pull-right" title="{{ $notification->created_at }}">
                <span class="glyphicon glyphicon-clock" aria-hidden="true"></span>
                {{ $notification->created_at->diffForHumans() }}
            </span>
        </div>
        <div class="reply-content">
            {!! $notification->data['reply_content'] !!}
        </div>
    </div>

以上就是通知消息的基本过程啦~~ 参考书籍《Laravel 教程 - Web 开发实战进阶 ( Laravel 5.5 )》,想学的小伙伴可以看看~