基於workerman實現的web消息推送站內信功能

流程說明

  • 使用 web-msg-sender 做爲 服務器監聽程序
  • 客戶端(瀏覽器)經過websocket鏈接 服務器監聽程序
  • 服務器應用程序(後端) 經過curl訪問 服務器監聽程序,將須要推送的信息發送給 服務器監聽程序
  • 服務器監聽程序 接收到後端發送的信息,廣播發送給全部客戶端,提示有新信息。
  • 客戶端 ajax訪問 後端,確認是否有發送給本身的站內信,若有,播放消息提示音,並更改頁面站內信未讀數。

文檔目錄
[TOC]php


服務器監聽

配置 服務器監聽程序

該程序對於php環境的要求是:css

  1. php cli >= 5.4,能夠運行命令 php -v查看版本
  2. linux系統要求php安裝了posix和pcntl擴展。

可使用 curl -Ss http://www.workerman.net/chec... | php 來檢測當前環境是否符合要求。若是不符合,須要根據提示安裝必要的擴展。html

環境檢測知足後,以ubuntu配置爲例來進行配置:前端

  1. 安裝相關擴展

$ sudo apt-get install php5-cli git gcc php-pear php5-dev libevent-dev -ylinux

  1. 安裝event擴展,==注意提示:Include libevent OpenSSL support [yes] : 時輸入no回車,其它直接敲回車就行==

$ pecl install eventgit

當出現Include libevent OpenSSL support [yes] :時,輸入nogithub

  1. 切換到root用戶,添加event.so到php-cli的php-ini文件中。

$ sudo suweb

$ echo extension=event.so > /etc/php5/cli/conf.d/event.iniajax

  1. 切換回普通用戶,切換到要保存項目的目錄,clone web-msg-sender項目

$ su nancyjson

$ cd /var/www

$ git clone https://github.com/walkor/web...

  1. 使用composer安裝,若是沒有安裝composer,請先安裝。

// 下載composer

$ curl -sS https://getcomposer.org/insta... | php

// 設置全局

$ sudo mv composer.phar /usr/local/bin/composer

// 查看是否安裝成功,若是有版本信息顯示,則說明安裝成功

$ composer -v

// 更新一下

$ composer self-update

// 進入到 web-msg-sender 項目中,使用composer進行安裝

$ cd /var/www/web-msg-sender/

==$ composer install==

開啓服務器監聽程序

進入該項目文件,啓動服務(以守護進程方式)

$ php start.php start -d

中止服務

$ php start.php stop

服務狀態

$ php start.php status

客戶端鏈接

客戶端(即咱們的前端代碼)使用 socket.io 插件經過websocket鏈接 服務器監聽程序

流程以下:

  1. 客戶端使用socket創建鏈接,鏈接成功後,以用戶實際的user_id發送登錄請求。
  2. 登錄請求成功,服務器監聽程序會以user_id做爲用戶的鏈接標識。
  3. 當接收到服務器監聽程序推送的信息,客戶端發送請求到後端程序,查詢是否有未讀的站內信。
  4. 若是有,客戶端播放消息聲音,而且更新頁面的站內信未讀數。

相關代碼以下:

// 引入前端文件
<script src='//cdn.bootcss.com/socket.io/1.3.7/socket.io.js'></script>

<script>
/*加載提示*/
function loadTip(hit) {
  $.ajax({
    url: "{{ url('/message/get_load') }}",
    type: 'get',
    success: function(msg) {
      if (msg.hit == 1 && hit==1)
        //播放消息提示音
        $(".tip-mp3")[0].play();
      if (msg.num > 0) {
        //顯示未讀消息數
        $(".message-tip").show(500);
        $(".message-tip").html(msg.num);
      } else
        $(".message-tip").hide(500);
    }
  });
}

// 初始化io對象
var socket = io('http://your.workerman.com:2120');
// uid 能夠爲網站用戶的uid,做爲例子這裏用session_id代替
var uid = '{{ Auth::user()->id }} ';
// 當socket鏈接後發送登陸請求
socket.on('connect', function(){socket.emit('login', uid);});
// 當服務端推送來消息時觸發,查詢後端程序
socket.on('new_msg', function(msg){loadTip(1);});
// 服務器端監聽程序推送來在線數據時
socket.on('update_online_count', function(online_stat){
    $("title").html("ERP "+online_stat);
});
</script>

後端業務處理

後端使用了Laravel第三方插件Notifynder 管理通知。它提供了一個完整的API來處理通知,例如存儲,檢索和組織代碼庫以處理數百個通知。

配置 Notifynder 插件

  1. 後端程序composer.json 文件的 require 中增長
"fenos/notifynder": "^4.0"
  1. 進入後端程序項目,輸入$ composer require fenos/notifynder 集成該插件。
  2. config/app.php 文件的 providers 數組中增長
Fenos\Notifynder\NotifynderServiceProvider::class,

在 aliases 數組中增長

'Notifynder' => Fenos\Notifynder\Facades\Notifynder::class,
  1. 使用一下命令發佈遷移以及配置notifynder

$ php artisan vendor:publish --provider="FenosNotifynderNotifynderServiceProvider"

$ php artisan migrate

  1. 在 User Model中使用FenosNotifynderNotifable,以ERP爲例,咱們的User Model是 app/Erp_company_user.php,在該文件增長引用。
use Fenos\Notifynder\Notifable;

class Erp_company_user extends Model implements AuthenticatableContract, CanResetPasswordContract {
    
    use Notifable;
    
}

這時,咱們只要使用 Erp_company_user model實例,就能夠調用 FenosNotifynderNotifable 中的方法。例如:

$user = Erp_company_user::first();
$notifications = $user->notifications;
  1. 配置 config/notifynder 文件。
  • 在 model 中配置 user model
'model' => 'App\Erp_company_user',

其餘的根據實際應用時更改配置。

後端業務代碼

  • 提供推送數據到 服務器監聽程序 的service。

將要推送的信息和推送的人等相關數據組裝好,使用curl遠程訪問 服務器監聽程序,監聽程序進行推送。

namespace App\Service\Setting;

use App\Service\CommonService;

class MessageService extends CommonService{
    // 指明給誰推送,爲空表示向全部在線用戶推送
    private $to_uid;
    // 推送的url地址,上線時改爲本身的服務器地址
    private $push_api_url = 'http://your.workerman.com:2121/';

    protected function set_url($push_api_url){
        $this->push_api_url=$push_api_url;
    }
    /**
    * 站內信推送
    * @param int to_uid
    * @return array  
    */
    public function sent_message($to_uid=''){
        $this->to_uid=$to_uid;
        $post_data = array(
        'type' => 'publish',
        'content' => 'You have a new message',
        'to' => $this->to_uid,
        );
        $ch = curl_init ();
        curl_setopt ( $ch, CURLOPT_URL, $this->push_api_url );
        curl_setopt ( $ch, CURLOPT_POST, 1 );
        curl_setopt ( $ch, CURLOPT_HEADER, 0 );
        curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, 1 );
        curl_setopt ( $ch, CURLOPT_POSTFIELDS, $post_data );
        $return = curl_exec ( $ch );
        curl_close ( $ch );
        return $return;
    }
}
  • 發送站內信

客戶端後端程序請求發送站內信。

後端程序 將站內信信息保存到 Notification_category 數據表中,將要指定要推送的人信息保存到 notifications 表中。

調用 上述的 MessageService 服務將信息推送到 服務器監聽程序

相關代碼以下:

// 保存站內信信息
$Notification_categorie = new Notification_category;
$Notification_categorie->name = $name;
$Notification_categorie->text = $text;
$Notification_categorie->save();

//站內信id
$this->categorie_id=$Notification_categorie->id;
$this->categorie_num=0;
                
try {
    //推送的人,這裏以發送全體爲例
    $users = Erp_company_user::all();
   
   //循環保存要通知的人站內信信息
    Notifynder::loop($users, function(NotifynderBuilder $builder, $user, $key) {
      $this->categorie_num=$key+1;
      $builder->category($this->categorie_id)
        ->from($this->user['id'])
        ->to($user->id);
    })->send();
} catch (EntityNotIterableException $e) {
} catch (IterableIsEmptyException $e) {
}
//推送到服務器端監聽程序
$sent_message = $this->MessageService->sent_message();
  • 接收站內信

查詢5分鐘內的站內信,是否有發送給本身的未讀信息,有的話,返回未讀信息數。

相關代碼以下:

//未讀站內信的數量
$not_read_num=$this->user->countNotificationsNotRead();
//是否提示新信息,看最新的站內信的時間是否在5分鐘內
$message=$this->user->getLastNotification();
if(empty($message))
    return array('num'=>0,'hit'=>0);
$message_time=$message->updated_at;
$five_minute_ago= Carbon::parse('-5 minute');
($message_time->gt($five_minute_ago) &&  $message->read==0 )? $hit=1 : $hit=0;
$result_array=array('num'=>$not_read_num,'hit'=>$hit);
return $result_array;
相關文章
相關標籤/搜索