当前位置:首页 > WebSocket > 正文内容

laravel利用websocket搭建一个简单的实时聊天系统

陈杰6个月前 (02-02)WebSocket1168

主要实现功能就是用户之间的的实时聊天。


理一下业务逻辑:


用户A给用户B发送消息

>如果用户B在线,直接通过websocket推送消息,用户B接受到消息后写入前端数据库,并归档数据

>如果用户B不在线,则暂存进mysql数据库。

>用户B不在线,打开进入APP,利用接口拉取历史消息,并归档存储进入数据库


<?php
/**
 * Author:陈杰
 * Blog:http://blog.95shouyou.com
 * Email:823380606@qq.com
 * Git:https://gitee.com/chen95
 * Date:2021/1/29 0029
 * Time:12:24
 */

namespace App\Http\Controllers\Member;

use App\Http\Controllers\Controller;

use App\Model\Member\MemberChatModel;
use GatewayClient\Gateway;
use Illuminate\Http\Request;

class ChatController extends Controller
{

    public function msg_list(Request $request)
    {
        $member_id = $request->get('member_id');
        $data      = MemberChatModel::suffix($member_id, 20)
            ->with("member:id,name,avatar")
            ->where("return_id", $member_id)
            ->get();
        for ($i = 0; $i < count($data); $i++) {
            $data[$i]->delete();
        }
        return self::success($data);
    }

    public function send(Request $request)
    {
        $rules  = [
            'return_id' => 'required|integer|min:1',
            'type'      => 'required|integer|in:1,2,3,4',
            'content'   => 'required|array'
        ];
        $params = self::checkValidate($rules, $request->all());

        $data = [
            'member_id'   => $request->get('member_id'),
            'return_id'   => $params['return_id'],
            'type'        => $params['type'],
            'content'     => $params['content'],
            'create_time' => time(),
        ];

        try {
            $is = Gateway::isUidOnline($params['return_id']);
            if ($is) {
                $msg = [
                    'type' => 101,
                    'msg'  => "ok",
                    'code' => 200,
                    'data' => $data,
                    'time' => time()
                ];
                Gateway::sendToUid($params['return_id'], json_encode($msg));
            } else {
                $model = new MemberChatModel();
                $model->setSuffix($data['return_id'], 20)->fill($data);
                $model->save();
            }
            return self::success($data);

        } catch (\Exception $exception) {
            return self::error($exception->getMessage());
        }
    }
}


理一下代码逻辑:


一个接口msg_list()就是我们的拉取历史消息,消息没有分类,需要前端自行归档。


接口send() 这里有一个发送人的id:member_id 和接收消息人的id:return_id。根据return_id取模做数据库分表。

因为用到的websocket是workerman,没有发送消息结果的回调,所以做了一个判断就是Gateway::isUinOnline,判断接收用户是否在线,在线的话就可以直接发送,不在线就暂存进数据库,等待用户打开APP自行拉取。


参数type决定发送的消息是文字,图片,视频等类型。

参数content是一个数组,例如是文字消息那么content={"text":"你好"}。如果是图片消息那么content={"url":"http://www.95shouyou.com"} 存储一个图片地址。。具体的跟前端同学自行商量就行了


看看Model

<?php
/**
 * Author:陈杰
 * Blog:http://blog.95shouyou.com
 * Email:823380606@qq.com
 * Git:https://gitee.com/chen95
 */

namespace App\Model\Member;

use App\Model\BaseModel;

class MemberChatModel extends BaseModel
{
    public $connection = "mysql_logs";
    public $timestamps = false;
    public $table = "member_chat";
    protected $casts = [
        'content' => 'array',
    ];
    public $fillable = ["member_id", "return_id", "type", "content", "create_time", "is"];

    public function member()
    {
        return $this->hasOne(MemberModel::class, 'id', 'member_id');
    }

    public function return_member()
    {
        return $this->hasOne(MemberModel::class, 'id', 'member_id');
    }
    
    // 设置表后缀
    public function setSuffix(int $suffix, int $mold)
    {
        if ($suffix > 0) {
            $suffix      = intval($suffix % $mold) + 1;
            $this->table = $this->getTable() . '_' . $suffix;
        }
        return $this;
    }
}


数据库结构


image.png

# Host: www.95shouyou.com  (Version: 5.7.32-log)
# Date: 2021-02-02 15:37:14
# Generator: MySQL-Front 5.3  (Build 4.234)

/*!40101 SET NAMES utf8 */;

#
# Structure for table "member_chat_1"
#

CREATE TABLE `member_chat_1` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `member_id` int(11) NOT NULL DEFAULT '0' COMMENT '发送人的id',
  `return_id` int(11) NOT NULL DEFAULT '0' COMMENT '接收人的id',
  `type` tinyint(3) NOT NULL DEFAULT '0' COMMENT '1文字,2图片,3视频,4位置',
  `content` text NOT NULL COMMENT '消息内容',
  `create_time` int(11) NOT NULL DEFAULT '0' COMMENT '创建时间',
  `is` tinyint(3) NOT NULL DEFAULT '0' COMMENT '0:未读  1已读',
  PRIMARY KEY (`id`),
  KEY `member_id` (`member_id`),
  KEY `return_id` (`return_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户聊天记录';


数据库: shenyanshe_log

表格: member_chat_1

备注: 用户聊天记录

索引:

名称类型属性备注
主索引idunique
member_idmember_id

return_idreturn_id


字段:

名称类型默认值属性备注
idint(11)<auto_increment>

member_idint(11)0
发送人的id
return_idint(11)0
接收人的id
typetinyint(3)0
1文字,2图片,3视频,4位置
contenttext

消息内容
create_timeint(11)0
创建时间
istinyint(3)0
0:未读 1已读


扫描二维码至手机访问

扫描二维码推送至手机访问。

版权声明:本文由何烦过虎溪发布,如需转载请注明出处。

转载请注明出处:http://95shouyou.com/?id=38

分享给朋友:
返回列表

上一篇:申研社websocket通信规定

没有最新的文章了...

相关文章

uniapp的websocket无法监听到onSocketClose和onSocketError

项目框架使用的前端uniapp+后端laravel+workerman websocket写的,主要功能是聊天室系统。但是在开发完成实际体验过程中发现了一个有趣的现象。websocket老是无缘无故的...

nginx下反向代理开启websocket的wss服务

nginx下反向代理开启websocket的wss服务

通过nginx配置好网站的ssl证书后添加   location /wss  {    proxy_pass http://127.0.0.1:828...

workerman中捕获notice错误并抛出异常

在workerman中出现了notice错误并不会中断程序运行,这是抛出一个无关紧要的提示,这显然与我们的程序设计初衷不符。例如我们去获取数组中的一个key-value值,当key不存在的时候只是提示...

Workerman-写一个简单的websocket双向通信并实现MVC,用来开发游戏服务器

最近在看Workerman,发现这是一个真的很好用的东西。文档相当丰富,而且大神walker很贴心,有问必答。下面记一下一个简单的基于GatewayWorker框架写的websocket的程序。传统的...

申研社websocket通信规定

一、建立连接和维持连接 1、建立连接 测试地址ws://api.shenyanshe.95shouyou.com/websocket 2、约定客户端发送数据格式为 json字符串,...

workerman拆分events文件,实现常规编程习惯

workerman拆分events文件,实现常规编程习惯

wokerman的gateway很好用,自动解决了扩展性,分布式等较底层的东西。所有的逻辑代码只需要专注于events.php文件就行了,但是作者对于events编程的介绍比较少,如果从业多年的老手自...

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。