├── application
├── .htaccess
├── socketio
│ ├── common.php
│ ├── controller
│ │ ├── Index.php
│ │ └── Server.php
│ ├── model
│ │ └── Msg.php
│ └── view
│ │ └── index
│ │ ├── chat.html
│ │ └── index.html
├── common.php
├── command.php
├── provider.php
├── tags.php
├── build.php
└── index
│ └── controller
│ └── Index.php
├── extend
└── .gitignore
├── runtime
└── .gitignore
├── public
├── robots.txt
├── favicon.ico
├── .htaccess
├── router.php
├── index.php
├── server.php
└── static
│ └── main.css
├── .gitignore
├── TODO.md
├── config
├── socketio
│ └── param.php
├── trace.php
├── middleware.php
├── console.php
├── cache.php
├── session.php
├── cookie.php
├── log.php
├── template.php
├── database.php
└── app.php
├── composer.json
├── think
├── route
└── route.php
├── msg.sql
├── LICENSE.txt
├── .travis.yml
├── README.md
└── composer.lock
/application/.htaccess:
--------------------------------------------------------------------------------
1 | deny from all
--------------------------------------------------------------------------------
/extend/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
--------------------------------------------------------------------------------
/runtime/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
--------------------------------------------------------------------------------
/public/robots.txt:
--------------------------------------------------------------------------------
1 | User-agent: *
2 | Disallow:
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /.idea
2 | /.vscode
3 | /vendor
4 | *.log
5 | thinkphp
6 | .env
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hsu1943/thinksocketio/HEAD/public/favicon.ico
--------------------------------------------------------------------------------
/TODO.md:
--------------------------------------------------------------------------------
1 | - 聊天室人数统计(已完成2019-06-19)
2 | - 私聊消息提醒(已完成2019-06-19)
3 | - 自定义用户昵称(已完成2019-06-19)
4 | - 历史消息查看
5 | - 输入中状态提示
--------------------------------------------------------------------------------
/public/.htaccess:
--------------------------------------------------------------------------------
1 |
2 | Options +FollowSymlinks -Multiviews
3 | RewriteEngine On
4 |
5 | RewriteCond %{REQUEST_FILENAME} !-d
6 | RewriteCond %{REQUEST_FILENAME} !-f
7 | RewriteRule ^(.*)$ index.php/$1 [QSA,PT,L]
8 |
9 |
--------------------------------------------------------------------------------
/config/socketio/param.php:
--------------------------------------------------------------------------------
1 | [
5 | 'port' => 2021, // 服务端端口号
6 | 'apiHost' => 'http://127.0.0.1:2121', // http api监听地址
7 | ],
8 |
9 | 'save_msg' => true, // 是否将消息存储到mysql,请保证mysql正常连接,并导入项目根目录socketio.sql
10 | ];
--------------------------------------------------------------------------------
/application/socketio/common.php:
--------------------------------------------------------------------------------
1 | 0; $i--) {
16 | $string .= $char[mt_rand(0, strlen($char) - 1)];
17 | }
18 |
19 | return $string;
20 | }
--------------------------------------------------------------------------------
/application/common.php:
--------------------------------------------------------------------------------
1 |
10 | // +----------------------------------------------------------------------
11 |
12 | // 应用公共文件
13 |
--------------------------------------------------------------------------------
/application/command.php:
--------------------------------------------------------------------------------
1 |
10 | // +----------------------------------------------------------------------
11 |
12 | return [];
13 |
--------------------------------------------------------------------------------
/application/provider.php:
--------------------------------------------------------------------------------
1 |
10 | // +----------------------------------------------------------------------
11 |
12 | // 应用容器绑定定义
13 | return [
14 | ];
15 |
--------------------------------------------------------------------------------
/public/router.php:
--------------------------------------------------------------------------------
1 |
10 | // +----------------------------------------------------------------------
11 | // $Id$
12 |
13 | if (is_file($_SERVER["DOCUMENT_ROOT"] . $_SERVER["SCRIPT_NAME"])) {
14 | return false;
15 | } else {
16 | require __DIR__ . "/index.php";
17 | }
18 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "topthink/think",
3 | "description": "the new thinkphp framework",
4 | "type": "project",
5 | "keywords": [
6 | "framework",
7 | "thinkphp",
8 | "ORM"
9 | ],
10 | "homepage": "http://thinkphp.cn/",
11 | "license": "Apache-2.0",
12 | "authors": [
13 | {
14 | "name": "liu21st",
15 | "email": "liu21st@gmail.com"
16 | }
17 | ],
18 | "require": {
19 | "php": ">=5.6.0",
20 | "topthink/framework": "5.1.*",
21 | "workerman/phpsocket.io": "^1.1"
22 | },
23 | "autoload": {
24 | "psr-4": {
25 | "app\\": "application"
26 | }
27 | },
28 | "extra": {
29 | "think-path": "thinkphp"
30 | },
31 | "config": {
32 | "preferred-install": "dist"
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/public/index.php:
--------------------------------------------------------------------------------
1 |
10 | // +----------------------------------------------------------------------
11 |
12 | // [ 应用入口文件 ]
13 | namespace think;
14 |
15 | // 加载基础文件
16 | require __DIR__ . '/../thinkphp/base.php';
17 |
18 | // 支持事先使用静态方法设置Request对象和Config对象
19 |
20 | // 执行应用并响应
21 | Container::get('app')->run()->send();
22 |
--------------------------------------------------------------------------------
/think:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env php
2 |
11 | // +----------------------------------------------------------------------
12 |
13 | namespace think;
14 |
15 | // 加载基础文件
16 | require __DIR__ . '/thinkphp/base.php';
17 |
18 | // 应用初始化
19 | Container::get('app')->path(__DIR__ . '/application/')->initialize();
20 |
21 | // 控制台初始化
22 | Console::init();
--------------------------------------------------------------------------------
/route/route.php:
--------------------------------------------------------------------------------
1 |
10 | // +----------------------------------------------------------------------
11 |
12 |
13 | Route::get('hello/:name', 'index/index/hello');
14 |
15 | Route::rule('socketio', 'socketio/index/index');
16 | Route::rule('chat', 'socketio/index/chat');
17 | Route::rule('system', 'socketio/index/system');
18 |
19 | return [
20 |
21 | ];
22 |
--------------------------------------------------------------------------------
/public/server.php:
--------------------------------------------------------------------------------
1 |
10 | // +----------------------------------------------------------------------
11 |
12 | // [ 应用入口文件 ]
13 | namespace think;
14 |
15 | // 加载基础文件
16 | require __DIR__ . '/../thinkphp/base.php';
17 |
18 | // 支持事先使用静态方法设置Request对象和Config对象
19 |
20 | // 执行应用并响应(绑定)
21 | Container::get('app')->bind('socketio/Server/index')->run()->send();
--------------------------------------------------------------------------------
/config/trace.php:
--------------------------------------------------------------------------------
1 |
10 | // +----------------------------------------------------------------------
11 |
12 | // +----------------------------------------------------------------------
13 | // | Trace设置 开启 app_trace 后 有效
14 | // +----------------------------------------------------------------------
15 | return [
16 | // 内置Html Console 支持扩展
17 | 'type' => 'Html',
18 | ];
19 |
--------------------------------------------------------------------------------
/config/middleware.php:
--------------------------------------------------------------------------------
1 |
10 | // +----------------------------------------------------------------------
11 |
12 | // +----------------------------------------------------------------------
13 | // | 中间件配置
14 | // +----------------------------------------------------------------------
15 | return [
16 | // 默认中间件命名空间
17 | 'default_namespace' => 'app\\http\\middleware\\',
18 | ];
19 |
--------------------------------------------------------------------------------
/application/socketio/controller/Index.php:
--------------------------------------------------------------------------------
1 | $username]);
29 | }
30 |
31 | public function system()
32 | {
33 | $data = Request::param();
34 | $to = $data['to'] ?? '';
35 | $content = $data['content'] ?? '';
36 | $res = Msg::send($to, $content);
37 | return $res == 'ok' ? '系统消息推送成功' : '系统消息推送失败';
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/config/console.php:
--------------------------------------------------------------------------------
1 |
10 | // +----------------------------------------------------------------------
11 |
12 | // +----------------------------------------------------------------------
13 | // | 控制台配置
14 | // +----------------------------------------------------------------------
15 | return [
16 | 'name' => 'Think Console',
17 | 'version' => '0.1',
18 | 'user' => null,
19 | ];
20 |
--------------------------------------------------------------------------------
/public/static/main.css:
--------------------------------------------------------------------------------
1 | .private-chat {
2 | color: #880000;
3 | }
4 | .open-chat {
5 | color: #4288ce;
6 | }
7 |
8 | .system-chat {
9 | color: blueviolet;
10 | }
11 |
12 | .user-name{
13 | color: green;
14 | }
15 |
16 | body {
17 | width: 90%;
18 | margin: 5% auto;
19 | }
20 |
21 | .fright {
22 | float: right;
23 | }
24 |
25 | .to {
26 | color: brown;
27 | }
28 |
29 | #chats-list{
30 | margin-left: -1em;
31 | }
32 |
33 | #chats-list li{
34 | line-height: 2em;
35 | list-style: none;
36 | }
37 |
38 | /* #chats-list li span{
39 | float: right;
40 | } */
41 |
42 | .me-say{
43 | float: right;
44 | color: #4288ce;
45 | }
46 |
47 | .clear {
48 | clear: both;
49 | }
50 |
51 | .header{
52 | width: 50%;
53 | text-align: center;
54 | margin-left: 25%;
55 | }
56 |
57 | .message{
58 | font-size: 1.5em;
59 | position: fixed;
60 | width: 90%;
61 | left: 5%;
62 | bottom: 1%;
63 | }
--------------------------------------------------------------------------------
/config/cache.php:
--------------------------------------------------------------------------------
1 |
10 | // +----------------------------------------------------------------------
11 |
12 | // +----------------------------------------------------------------------
13 | // | 缓存设置
14 | // +----------------------------------------------------------------------
15 |
16 | return [
17 | // 驱动方式
18 | 'type' => 'File',
19 | // 缓存保存目录
20 | 'path' => '',
21 | // 缓存前缀
22 | 'prefix' => '',
23 | // 缓存有效期 0表示永久缓存
24 | 'expire' => 0,
25 | ];
26 |
--------------------------------------------------------------------------------
/application/tags.php:
--------------------------------------------------------------------------------
1 |
10 | // +----------------------------------------------------------------------
11 |
12 | // 应用行为扩展定义文件
13 | return [
14 | // 应用初始化
15 | 'app_init' => [],
16 | // 应用开始
17 | 'app_begin' => [],
18 | // 模块初始化
19 | 'module_init' => [],
20 | // 操作开始执行
21 | 'action_begin' => [],
22 | // 视图内容过滤
23 | 'view_filter' => [],
24 | // 日志写入
25 | 'log_write' => [],
26 | // 应用结束
27 | 'app_end' => [],
28 | ];
29 |
--------------------------------------------------------------------------------
/application/build.php:
--------------------------------------------------------------------------------
1 |
10 | // +----------------------------------------------------------------------
11 |
12 | return [
13 | // 生成应用公共文件
14 | '__file__' => ['common.php'],
15 | // 定义socketio模块的自动生成
16 | 'socketio' => [
17 | '__file__' => ['common.php'],
18 | '__dir__' => ['controller', 'model', 'view'],
19 | 'controller' => ['Index', 'Server'],
20 | 'model' => [],
21 | 'view' => ['index/index'],
22 | ],
23 | // 其他更多的模块定义
24 | ];
25 |
--------------------------------------------------------------------------------
/application/index/controller/Index.php:
--------------------------------------------------------------------------------
1 | *{ padding: 0; margin: 0; } div{ padding: 4px 48px;} a{color:#2E5CD5;cursor: pointer;text-decoration: none} a:hover{text-decoration:underline; } body{ background: #fff; font-family: "Century Gothic","Microsoft yahei"; color: #333;font-size:18px;} h1{ font-size: 100px; font-weight: normal; margin-bottom: 12px; } p{ line-height: 1.6em; font-size: 42px }
:)
ThinkPHP V5.1
12载初心不改(2006-2018) - 你值得信赖的PHP框架
';
9 | }
10 |
11 | public function hello($name = 'ThinkPHP5')
12 | {
13 | return 'hello,' . $name;
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/config/session.php:
--------------------------------------------------------------------------------
1 |
10 | // +----------------------------------------------------------------------
11 |
12 | // +----------------------------------------------------------------------
13 | // | 会话设置
14 | // +----------------------------------------------------------------------
15 |
16 | return [
17 | 'id' => '',
18 | // SESSION_ID的提交变量,解决flash上传跨域
19 | 'var_session_id' => '',
20 | // SESSION 前缀
21 | 'prefix' => 'think',
22 | // 驱动方式 支持redis memcache memcached
23 | 'type' => '',
24 | // 是否自动开启 SESSION
25 | 'auto_start' => true,
26 | ];
27 |
--------------------------------------------------------------------------------
/config/cookie.php:
--------------------------------------------------------------------------------
1 |
10 | // +----------------------------------------------------------------------
11 |
12 | // +----------------------------------------------------------------------
13 | // | Cookie设置
14 | // +----------------------------------------------------------------------
15 | return [
16 | // cookie 名称前缀
17 | 'prefix' => '',
18 | // cookie 保存时间
19 | 'expire' => 0,
20 | // cookie 保存路径
21 | 'path' => '/',
22 | // cookie 有效域名
23 | 'domain' => '',
24 | // cookie 启用安全传输
25 | 'secure' => false,
26 | // httponly设置
27 | 'httponly' => '',
28 | // 是否使用 setcookie
29 | 'setcookie' => true,
30 | ];
31 |
--------------------------------------------------------------------------------
/config/log.php:
--------------------------------------------------------------------------------
1 |
10 | // +----------------------------------------------------------------------
11 |
12 | // +----------------------------------------------------------------------
13 | // | 日志设置
14 | // +----------------------------------------------------------------------
15 | return [
16 | // 日志记录方式,内置 file socket 支持扩展
17 | 'type' => 'File',
18 | // 日志保存目录
19 | 'path' => '../logs/',
20 | // 日志记录级别
21 | 'level' => [],
22 | // 单文件日志写入
23 | 'single' => false,
24 | // 独立日志级别
25 | 'apart_level' => [],
26 | // 最大日志文件数量
27 | 'max_files' => 30,
28 | // 是否关闭日志写入
29 | 'close' => false,
30 | ];
31 |
--------------------------------------------------------------------------------
/application/socketio/model/Msg.php:
--------------------------------------------------------------------------------
1 | "publish",
34 | "content" => $content ?: '推送消息为空',
35 | "to" => $to,
36 | );
37 | $ch = curl_init();
38 | curl_setopt($ch, CURLOPT_URL, $push_api_url);
39 | curl_setopt($ch, CURLOPT_POST, 1);
40 | curl_setopt($ch, CURLOPT_HEADER, 0);
41 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
42 | curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
43 | curl_setopt($ch, CURLOPT_HTTPHEADER, array("Expect:"));
44 | $return = curl_exec($ch);
45 | curl_close($ch);
46 | return $return;
47 | }
48 | }
--------------------------------------------------------------------------------
/msg.sql:
--------------------------------------------------------------------------------
1 | /*
2 | Navicat Premium Data Transfer
3 |
4 | Source Server : localhost
5 | Source Server Type : MySQL
6 | Source Server Version : 100137
7 | Source Host : 127.0.0.1:3306
8 | Source Schema : socket
9 |
10 | Target Server Type : MySQL
11 | Target Server Version : 100137
12 | File Encoding : 65001
13 |
14 | Date: 19/12/2019 11:00:05
15 | */
16 |
17 | SET NAMES utf8mb4;
18 | SET FOREIGN_KEY_CHECKS = 0;
19 |
20 | -- ----------------------------
21 | -- Table structure for msg
22 | -- ----------------------------
23 | DROP TABLE IF EXISTS `msg`;
24 | CREATE TABLE `msg` (
25 | `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
26 | `msg` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '消息',
27 | `from` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '来自用户',
28 | `to` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '发送给用户',
29 | `type` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '消息类型',
30 | `create_time` timestamp(0) NULL DEFAULT CURRENT_TIMESTAMP COMMENT '发送时间',
31 | PRIMARY KEY (`id`) USING BTREE
32 | ) ENGINE = InnoDB AUTO_INCREMENT = 216 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '消息记录' ROW_FORMAT = Compact;
33 |
34 | SET FOREIGN_KEY_CHECKS = 1;
35 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 |
2 | ThinkPHP遵循Apache2开源协议发布,并提供免费使用。
3 | 版权所有Copyright © 2006-2016 by ThinkPHP (http://thinkphp.cn)
4 | All rights reserved。
5 | ThinkPHP® 商标和著作权所有者为上海顶想信息科技有限公司。
6 |
7 | Apache Licence是著名的非盈利开源组织Apache采用的协议。
8 | 该协议和BSD类似,鼓励代码共享和尊重原作者的著作权,
9 | 允许代码修改,再作为开源或商业软件发布。需要满足
10 | 的条件:
11 | 1. 需要给代码的用户一份Apache Licence ;
12 | 2. 如果你修改了代码,需要在被修改的文件中说明;
13 | 3. 在延伸的代码中(修改和有源代码衍生的代码中)需要
14 | 带有原来代码中的协议,商标,专利声明和其他原来作者规
15 | 定需要包含的说明;
16 | 4. 如果再发布的产品中包含一个Notice文件,则在Notice文
17 | 件中需要带有本协议内容。你可以在Notice中增加自己的
18 | 许可,但不可以表现为对Apache Licence构成更改。
19 | 具体的协议参考:http://www.apache.org/licenses/LICENSE-2.0
20 |
21 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 | COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 | POSSIBILITY OF SUCH DAMAGE.
33 |
--------------------------------------------------------------------------------
/config/template.php:
--------------------------------------------------------------------------------
1 |
10 | // +----------------------------------------------------------------------
11 |
12 | // +----------------------------------------------------------------------
13 | // | 模板设置
14 | // +----------------------------------------------------------------------
15 |
16 | return [
17 | // 模板引擎类型 支持 php think 支持扩展
18 | 'type' => 'Think',
19 | // 默认模板渲染规则 1 解析为小写+下划线 2 全部转换小写 3 保持操作方法
20 | 'auto_rule' => 1,
21 | // 模板路径
22 | 'view_path' => '',
23 | // 模板后缀
24 | 'view_suffix' => 'html',
25 | // 模板文件名分隔符
26 | 'view_depr' => DIRECTORY_SEPARATOR,
27 | // 模板引擎普通标签开始标记
28 | 'tpl_begin' => '{',
29 | // 模板引擎普通标签结束标记
30 | 'tpl_end' => '}',
31 | // 标签库标签开始标记
32 | 'taglib_begin' => '{',
33 | // 标签库标签结束标记
34 | 'taglib_end' => '}',
35 |
36 | 'tpl_replace_string' => [
37 | '__STATIC__' => '/static'
38 | ],
39 | ];
40 |
--------------------------------------------------------------------------------
/config/database.php:
--------------------------------------------------------------------------------
1 |
10 | // +----------------------------------------------------------------------
11 |
12 | return [
13 | // 数据库类型
14 | 'type' => 'mysql',
15 | // 服务器地址
16 | 'hostname' => 'localhost',
17 | // 数据库名
18 | 'database' => 'socket',
19 | // 用户名
20 | 'username' => 'root',
21 | // 密码
22 | 'password' => 'root',
23 | // 端口
24 | 'hostport' => '3306',
25 | // 连接dsn
26 | 'dsn' => '',
27 | // 数据库连接参数
28 | 'params' => [],
29 | // 数据库编码默认采用utf8
30 | 'charset' => 'utf8',
31 | // 数据库表前缀
32 | 'prefix' => '',
33 | // 数据库调试模式
34 | 'debug' => true,
35 | // 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器)
36 | 'deploy' => 0,
37 | // 数据库读写是否分离 主从式有效
38 | 'rw_separate' => false,
39 | // 读写分离后 主服务器数量
40 | 'master_num' => 1,
41 | // 指定从服务器序号
42 | 'slave_no' => '',
43 | // 自动读取主库数据
44 | 'read_master' => false,
45 | // 是否严格检查字段是否存在
46 | 'fields_strict' => true,
47 | // 数据集返回类型
48 | 'resultset_type' => 'array',
49 | // 自动写入时间戳字段
50 | 'auto_timestamp' => false,
51 | // 时间字段取出后的默认时间格式
52 | 'datetime_format' => 'Y-m-d H:i:s',
53 | // 是否需要进行SQL性能分析
54 | 'sql_explain' => false,
55 | // Builder类
56 | 'builder' => '',
57 | // Query类
58 | 'query' => '\\think\\db\\Query',
59 | // 是否需要断线重连
60 | 'break_reconnect' => false,
61 | // 断线标识字符串
62 | 'break_match_str' => [],
63 | ];
64 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo: false
2 |
3 | language: php
4 |
5 | branches:
6 | only:
7 | - stable
8 |
9 | cache:
10 | directories:
11 | - $HOME/.composer/cache
12 |
13 | before_install:
14 | - composer self-update
15 |
16 | install:
17 | - composer install --no-dev --no-interaction --ignore-platform-reqs
18 | - zip -r --exclude='*.git*' --exclude='*.zip' --exclude='*.travis.yml' ThinkPHP_Core.zip .
19 | - composer require --update-no-dev --no-interaction "topthink/think-image:^1.0"
20 | - composer require --update-no-dev --no-interaction "topthink/think-migration:^1.0"
21 | - composer require --update-no-dev --no-interaction "topthink/think-captcha:^1.0"
22 | - composer require --update-no-dev --no-interaction "topthink/think-mongo:^1.0"
23 | - composer require --update-no-dev --no-interaction "topthink/think-worker:^1.0"
24 | - composer require --update-no-dev --no-interaction "topthink/think-helper:^1.0"
25 | - composer require --update-no-dev --no-interaction "topthink/think-queue:^1.0"
26 | - composer require --update-no-dev --no-interaction "topthink/think-angular:^1.0"
27 | - composer require --dev --update-no-dev --no-interaction "topthink/think-testing:^1.0"
28 | - zip -r --exclude='*.git*' --exclude='*.zip' --exclude='*.travis.yml' ThinkPHP_Full.zip .
29 |
30 | script:
31 | - php think unit
32 |
33 | deploy:
34 | provider: releases
35 | api_key:
36 | secure: TSF6bnl2JYN72UQOORAJYL+CqIryP2gHVKt6grfveQ7d9rleAEoxlq6PWxbvTI4jZ5nrPpUcBUpWIJHNgVcs+bzLFtyh5THaLqm39uCgBbrW7M8rI26L8sBh/6nsdtGgdeQrO/cLu31QoTzbwuz1WfAVoCdCkOSZeXyT/CclH99qV6RYyQYqaD2wpRjrhA5O4fSsEkiPVuk0GaOogFlrQHx+C+lHnf6pa1KxEoN1A0UxxVfGX6K4y5g4WQDO5zT4bLeubkWOXK0G51XSvACDOZVIyLdjApaOFTwamPcD3S1tfvuxRWWvsCD5ljFvb2kSmx5BIBNwN80MzuBmrGIC27XLGOxyMerwKxB6DskNUO9PflKHDPI61DRq0FTy1fv70SFMSiAtUv9aJRT41NQh9iJJ0vC8dl+xcxrWIjU1GG6+l/ZcRqVx9V1VuGQsLKndGhja7SQ+X1slHl76fRq223sMOql7MFCd0vvvxVQ2V39CcFKao/LB1aPH3VhODDEyxwx6aXoTznvC/QPepgWsHOWQzKj9ftsgDbsNiyFlXL4cu8DWUty6rQy8zT2b4O8b1xjcwSUCsy+auEjBamzQkMJFNlZAIUrukL/NbUhQU37TAbwsFyz7X0E/u/VMle/nBCNAzgkMwAUjiHM6FqrKKBRWFbPrSIixjfjkCnrMEPw=
37 | file:
38 | - ThinkPHP_Core.zip
39 | - ThinkPHP_Full.zip
40 | skip_cleanup: true
41 | on:
42 | tags: true
43 |
--------------------------------------------------------------------------------
/application/socketio/view/index/chat.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 与{$to}私聊
7 |
8 |
9 |
10 |
11 |
13 |
14 | 消息:
15 |
16 |
17 | 消息列表:
18 |
23 |
24 |
25 |
26 |
27 |
82 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## 简介
2 |
3 | 一个使用PHPSocket.IO,ThinkPHP5.1,以及JQ实现的聊天室,包括功能有:
4 |
5 | - 公频广场聊天
6 | - 自定义用户名
7 | - 一对一私聊
8 | - 公频中私聊信息提醒
9 | - 新用户加入以及离开提醒
10 | - 在线用户列表,人数统计
11 | - 系统主动推送广播,或向指定用户推送消息
12 |
13 | ## 截图
14 |
15 | 广场公频聊天:
16 |
17 | 一对一私聊:
18 |
19 | 广播推送系统消息:
20 |
21 | 指定用户推送消息:
22 |
23 |
24 | ## 使用说明
25 |
26 | 以下说明假定已经为项目`public`目录绑定了域名`test.com`并正确部署服务器,访问`test.com`能看到TP5默认首页。
27 |
28 | 如果修改了配置或者代码,请重新运行服务端,否则代码不生效。
29 |
30 | ### 安装
31 |
32 | ```bash
33 | git clone git@github.com:hsu1943/thinksocketio.git
34 | cd thinksocketio
35 | composer install -vvv
36 | ```
37 |
38 | ### 配置
39 |
40 | 模板文件`/application/socketio/view/index/index.html`和`/application/socketio/view/index/chat.html`中`socket`修改为你的`socket`服务端地址,默认测试端口2021,端口号可以在`/config/socketio/param.php`中配置。这里是本机测试,用`http://127.0.0.1:2021`。
41 |
42 | ```bash
43 | var socket = io('http://127.0.0.1:2021');
44 | ```
45 | ### 使用数据库记录消息:
46 |
47 | 如果你需要使用数据库存储消息,按照下面的步骤打开配置,打开配置后系统会根据昵称将所有聊天记录写入数据库`msg`表中,包括主动推送的消息;
48 |
49 | 1. 在`config/database.php`中配置数据库,保证数据库能正确连接;
50 | 2. 导入根目录下`msg.sql`到数据库;
51 | 3. 在`config/socketio/param.php`中将`save_msg`修改为`true`(默认是`false`,不写入到数据库);
52 |
53 | 这里说明一下,请保证数据库能正确连接并且里面有正确的表结构(第二步导入表)再进行第三步配置。
54 |
55 | ### 主动推送系统消息接口
56 |
57 | 修改配置文件`/config/socketio/param.php`中的配置为监听消息推送地址,这里本地测试,使用本地2121端口;
58 |
59 | ```bash
60 | return [
61 | 'ws' => [
62 | 'apiHost' => 'http://127.0.0.1:2121',
63 | ],
64 | ];
65 | ```
66 |
67 | 该地址即系统推送消息地址,参数:
68 |
69 | ```html
70 | to:接收人
71 | content:消息
72 | ```
73 |
74 | 两种用法:
75 |
76 | 1. 其他项目POST或GET请求接口即可推送消息
77 |
78 | ```html
79 | 向username推送系统消息
80 | http://test.com/system?to=username&content=系统推送消息测试
81 | 广播消息
82 | http://test.com/system?content=系统推送消息测试
83 | ```
84 |
85 | `http://test.com/system`这是本项目使用上面的监听地址做的一个消息推送demo,详情看源代码。
86 |
87 | 2. 本项目中推送系统消息:
88 |
89 | 已将推送封装在Msg的模型中,使用:
90 |
91 | ```php
92 | $res = Msg::send($to, $content);
93 | return $res == 'ok' ? '系统消息推送成功' : '系统消息推送失败';
94 | ```
95 |
96 | ## 测试
97 |
98 | 运行服务端:
99 |
100 | ```bash
101 | php ./public/server.php
102 | ```
103 | 这里可以将输出写到某个日志文件中,或者使用`supervisor`来管理服务端。
104 |
105 | 访问以下地址即可进入公频:
106 |
107 | ```bash
108 | http://test.com/socketio
109 | ```
110 |
111 | 点击消息列表中的用户名即可进入私聊。
112 |
113 | ## 更新
114 |
115 | * 2019-12-19 增加服务端的输出,以及端口配置项,保存数据库加上错误处理,更新项目README;
116 | * 2019-06-19 增加在线人数统计,在线用户列表,修改昵称,添加系统主动推送接口(广播或私信);
117 |
118 | ## 开发记录
119 |
120 | 以下两篇文章是在开发过程中的记录,代码不是最新,最新代码以本项目`github`为准,有问题可以去文章里留言。
121 |
122 | [ThinkPHP 5.1+PHPSocket.IO实现websocket搭建聊天室+私聊](https://beltxman.com/archives/2329.html "ThinkPHP 5.1+PHPSocket.IO实现websocket搭建聊天室+私聊")
123 |
124 | [ThinkPHP 5.1下使用PHPSocket.IO实现websocket通讯](https://beltxman.com/archives/1885.html "ThinkPHP 5.1下使用PHPSocket.IO实现websocket通讯")
125 |
126 | ## 感谢
127 |
128 | * top-think/framework
129 | * walkor/phpsocket.io
130 | * walkor/web-msg-sender
--------------------------------------------------------------------------------
/config/app.php:
--------------------------------------------------------------------------------
1 |
10 | // +----------------------------------------------------------------------
11 |
12 | // +----------------------------------------------------------------------
13 | // | 应用设置
14 | // +----------------------------------------------------------------------
15 |
16 | return [
17 | // 应用名称
18 | 'app_name' => '',
19 | // 应用地址
20 | 'app_host' => '',
21 | // 应用调试模式
22 | 'app_debug' => true,
23 | // 应用Trace
24 | 'app_trace' => false,
25 | // 是否支持多模块
26 | 'app_multi_module' => true,
27 | // 入口自动绑定模块
28 | 'auto_bind_module' => false,
29 | // 注册的根命名空间
30 | 'root_namespace' => [],
31 | // 默认输出类型
32 | 'default_return_type' => 'html',
33 | // 默认AJAX 数据返回格式,可选json xml ...
34 | 'default_ajax_return' => 'json',
35 | // 默认JSONP格式返回的处理方法
36 | 'default_jsonp_handler' => 'jsonpReturn',
37 | // 默认JSONP处理方法
38 | 'var_jsonp_handler' => 'callback',
39 | // 默认时区
40 | 'default_timezone' => 'Asia/Shanghai',
41 | // 是否开启多语言
42 | 'lang_switch_on' => false,
43 | // 默认全局过滤方法 用逗号分隔多个
44 | 'default_filter' => '',
45 | // 默认语言
46 | 'default_lang' => 'zh-cn',
47 | // 应用类库后缀
48 | 'class_suffix' => false,
49 | // 控制器类后缀
50 | 'controller_suffix' => false,
51 |
52 | // +----------------------------------------------------------------------
53 | // | 模块设置
54 | // +----------------------------------------------------------------------
55 |
56 | // 默认模块名
57 | 'default_module' => 'index',
58 | // 禁止访问模块
59 | 'deny_module_list' => ['common'],
60 | // 默认控制器名
61 | 'default_controller' => 'Index',
62 | // 默认操作名
63 | 'default_action' => 'index',
64 | // 默认验证器
65 | 'default_validate' => '',
66 | // 默认的空模块名
67 | 'empty_module' => '',
68 | // 默认的空控制器名
69 | 'empty_controller' => 'Error',
70 | // 操作方法前缀
71 | 'use_action_prefix' => false,
72 | // 操作方法后缀
73 | 'action_suffix' => '',
74 | // 自动搜索控制器
75 | 'controller_auto_search' => false,
76 |
77 | // +----------------------------------------------------------------------
78 | // | URL设置
79 | // +----------------------------------------------------------------------
80 |
81 | // PATHINFO变量名 用于兼容模式
82 | 'var_pathinfo' => 's',
83 | // 兼容PATH_INFO获取
84 | 'pathinfo_fetch' => ['ORIG_PATH_INFO', 'REDIRECT_PATH_INFO', 'REDIRECT_URL'],
85 | // pathinfo分隔符
86 | 'pathinfo_depr' => '/',
87 | // HTTPS代理标识
88 | 'https_agent_name' => '',
89 | // IP代理获取标识
90 | 'http_agent_ip' => 'X-REAL-IP',
91 | // URL伪静态后缀
92 | 'url_html_suffix' => 'html',
93 | // URL普通方式参数 用于自动生成
94 | 'url_common_param' => false,
95 | // URL参数方式 0 按名称成对解析 1 按顺序解析
96 | 'url_param_type' => 0,
97 | // 是否开启路由延迟解析
98 | 'url_lazy_route' => false,
99 | // 是否强制使用路由
100 | 'url_route_must' => false,
101 | // 合并路由规则
102 | 'route_rule_merge' => false,
103 | // 路由是否完全匹配
104 | 'route_complete_match' => false,
105 | // 使用注解路由
106 | 'route_annotation' => false,
107 | // 域名根,如thinkphp.cn
108 | 'url_domain_root' => '',
109 | // 是否自动转换URL中的控制器和操作名
110 | 'url_convert' => true,
111 | // 默认的访问控制器层
112 | 'url_controller_layer' => 'controller',
113 | // 表单请求类型伪装变量
114 | 'var_method' => '_method',
115 | // 表单ajax伪装变量
116 | 'var_ajax' => '_ajax',
117 | // 表单pjax伪装变量
118 | 'var_pjax' => '_pjax',
119 | // 是否开启请求缓存 true自动缓存 支持设置请求缓存规则
120 | 'request_cache' => false,
121 | // 请求缓存有效期
122 | 'request_cache_expire' => null,
123 | // 全局请求缓存排除规则
124 | 'request_cache_except' => [],
125 | // 是否开启路由缓存
126 | 'route_check_cache' => false,
127 | // 路由缓存的Key自定义设置(闭包),默认为当前URL和请求类型的md5
128 | 'route_check_cache_key' => '',
129 | // 路由缓存类型及参数
130 | 'route_cache_option' => [],
131 |
132 | // 默认跳转页面对应的模板文件
133 | 'dispatch_success_tmpl' => Env::get('think_path') . 'tpl/dispatch_jump.tpl',
134 | 'dispatch_error_tmpl' => Env::get('think_path') . 'tpl/dispatch_jump.tpl',
135 |
136 | // 异常页面的模板文件
137 | 'exception_tmpl' => Env::get('think_path') . 'tpl/think_exception.tpl',
138 |
139 | // 错误显示信息,非调试模式有效
140 | 'error_message' => '页面错误!请稍后再试~',
141 | // 显示错误信息
142 | 'show_error_msg' => false,
143 | // 异常处理handle类 留空使用 \think\exception\Handle
144 | 'exception_handle' => '',
145 |
146 | ];
147 |
--------------------------------------------------------------------------------
/application/socketio/view/index/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 测试WebSocket聊天室
7 |
8 |
9 |
10 |
11 | 当前用户【】
12 |
13 |
14 |
15 | 昵称:
16 |
17 |
18 |
19 | 消息:
20 |
21 |
22 |
23 |
29 |
30 |
动态
31 |
34 |
系统消息
35 |
38 |
在线()
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
194 |
--------------------------------------------------------------------------------
/composer.lock:
--------------------------------------------------------------------------------
1 | {
2 | "_readme": [
3 | "This file locks the dependencies of your project to a known state",
4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
5 | "This file is @generated automatically"
6 | ],
7 | "content-hash": "c949e593f4d8e034a6be41c92b7b4871",
8 | "packages": [
9 | {
10 | "name": "topthink/framework",
11 | "version": "v5.1.18",
12 | "source": {
13 | "type": "git",
14 | "url": "https://github.com/top-think/framework.git",
15 | "reference": "833fcaf0f29f23bdceaae655f64d10c18b9bf562"
16 | },
17 | "dist": {
18 | "type": "zip",
19 | "url": "https://files.phpcomposer.com/files/top-think/framework/833fcaf0f29f23bdceaae655f64d10c18b9bf562.zip",
20 | "reference": "833fcaf0f29f23bdceaae655f64d10c18b9bf562",
21 | "shasum": ""
22 | },
23 | "require": {
24 | "php": ">=5.6.0",
25 | "topthink/think-installer": "2.*"
26 | },
27 | "require-dev": {
28 | "johnkary/phpunit-speedtrap": "^1.0",
29 | "mikey179/vfsstream": "~1.6",
30 | "phpdocumentor/reflection-docblock": "^2.0",
31 | "phploc/phploc": "2.*",
32 | "phpunit/phpunit": "^5.0|^6.0",
33 | "sebastian/phpcpd": "2.*",
34 | "squizlabs/php_codesniffer": "2.*"
35 | },
36 | "type": "think-framework",
37 | "notification-url": "https://packagist.org/downloads/",
38 | "license": [
39 | "Apache-2.0"
40 | ],
41 | "authors": [
42 | {
43 | "name": "liu21st",
44 | "email": "liu21st@gmail.com"
45 | },
46 | {
47 | "name": "yunwuxin",
48 | "email": "448901948@qq.com"
49 | }
50 | ],
51 | "description": "the new thinkphp framework",
52 | "homepage": "http://thinkphp.cn/",
53 | "keywords": [
54 | "framework",
55 | "orm",
56 | "thinkphp"
57 | ],
58 | "time": "2018-07-02T05:29:17+00:00"
59 | },
60 | {
61 | "name": "topthink/think-installer",
62 | "version": "v2.0.0",
63 | "source": {
64 | "type": "git",
65 | "url": "https://github.com/top-think/think-installer.git",
66 | "reference": "f5400a12c60e513911aef41fe443fa6920952675"
67 | },
68 | "dist": {
69 | "type": "zip",
70 | "url": "https://files.phpcomposer.com/files/top-think/think-installer/f5400a12c60e513911aef41fe443fa6920952675.zip",
71 | "reference": "f5400a12c60e513911aef41fe443fa6920952675",
72 | "shasum": ""
73 | },
74 | "require": {
75 | "composer-plugin-api": "^1.0"
76 | },
77 | "require-dev": {
78 | "composer/composer": "1.0.*@dev"
79 | },
80 | "type": "composer-plugin",
81 | "extra": {
82 | "class": "think\\composer\\Plugin"
83 | },
84 | "autoload": {
85 | "psr-4": {
86 | "think\\composer\\": "src"
87 | }
88 | },
89 | "notification-url": "https://packagist.org/downloads/",
90 | "license": [
91 | "Apache-2.0"
92 | ],
93 | "authors": [
94 | {
95 | "name": "yunwuxin",
96 | "email": "448901948@qq.com"
97 | }
98 | ],
99 | "time": "2018-05-11T06:45:42+00:00"
100 | },
101 | {
102 | "name": "workerman/channel",
103 | "version": "v1.0.5",
104 | "source": {
105 | "type": "git",
106 | "url": "https://github.com/walkor/Channel.git",
107 | "reference": "0836a9a413c6e8425ee36307d95e2e49cc380f50"
108 | },
109 | "dist": {
110 | "type": "zip",
111 | "url": "https://files.phpcomposer.com/files/walkor/Channel/0836a9a413c6e8425ee36307d95e2e49cc380f50.zip",
112 | "reference": "0836a9a413c6e8425ee36307d95e2e49cc380f50",
113 | "shasum": ""
114 | },
115 | "require": {
116 | "workerman/workerman": ">=3.3.0"
117 | },
118 | "type": "library",
119 | "autoload": {
120 | "psr-4": {
121 | "Channel\\": "./src"
122 | }
123 | },
124 | "notification-url": "https://packagist.org/downloads/",
125 | "license": [
126 | "MIT"
127 | ],
128 | "homepage": "http://www.workerman.net",
129 | "time": "2018-07-02T02:42:37+00:00"
130 | },
131 | {
132 | "name": "workerman/phpsocket.io",
133 | "version": "v1.1.9",
134 | "source": {
135 | "type": "git",
136 | "url": "https://github.com/walkor/phpsocket.io.git",
137 | "reference": "8ee5fd56ea364e99c6428dd5df04b730f92e7d91"
138 | },
139 | "dist": {
140 | "type": "zip",
141 | "url": "https://files.phpcomposer.com/files/walkor/phpsocket.io/8ee5fd56ea364e99c6428dd5df04b730f92e7d91.zip",
142 | "reference": "8ee5fd56ea364e99c6428dd5df04b730f92e7d91",
143 | "shasum": ""
144 | },
145 | "require": {
146 | "workerman/channel": ">=1.0.0",
147 | "workerman/workerman": ">=3.1.8"
148 | },
149 | "type": "library",
150 | "autoload": {
151 | "psr-4": {
152 | "PHPSocketIO\\": "./src"
153 | }
154 | },
155 | "notification-url": "https://packagist.org/downloads/",
156 | "license": [
157 | "MIT"
158 | ],
159 | "homepage": "http://www.workerman.net",
160 | "keywords": [
161 | "Socket.io"
162 | ],
163 | "time": "2018-04-15T14:03:37+00:00"
164 | },
165 | {
166 | "name": "workerman/workerman",
167 | "version": "v3.5.11",
168 | "source": {
169 | "type": "git",
170 | "url": "https://github.com/walkor/Workerman.git",
171 | "reference": "c83e189b5855d91f99a7d01ac58f5bbc7161b5e5"
172 | },
173 | "dist": {
174 | "type": "zip",
175 | "url": "https://files.phpcomposer.com/files/walkor/Workerman/c83e189b5855d91f99a7d01ac58f5bbc7161b5e5.zip",
176 | "reference": "c83e189b5855d91f99a7d01ac58f5bbc7161b5e5",
177 | "shasum": ""
178 | },
179 | "require": {
180 | "php": ">=5.3"
181 | },
182 | "suggest": {
183 | "ext-event": "For better performance. "
184 | },
185 | "type": "library",
186 | "autoload": {
187 | "psr-4": {
188 | "Workerman\\": "./"
189 | }
190 | },
191 | "notification-url": "https://packagist.org/downloads/",
192 | "license": [
193 | "MIT"
194 | ],
195 | "authors": [
196 | {
197 | "name": "walkor",
198 | "email": "walkor@workerman.net",
199 | "homepage": "http://www.workerman.net",
200 | "role": "Developer"
201 | }
202 | ],
203 | "description": "An asynchronous event driven PHP framework for easily building fast, scalable network applications.",
204 | "homepage": "http://www.workerman.net",
205 | "keywords": [
206 | "asynchronous",
207 | "event-loop"
208 | ],
209 | "time": "2018-06-07T09:36:14+00:00"
210 | }
211 | ],
212 | "packages-dev": [],
213 | "aliases": [],
214 | "minimum-stability": "stable",
215 | "stability-flags": [],
216 | "prefer-stable": false,
217 | "prefer-lowest": false,
218 | "platform": {
219 | "php": ">=5.6.0"
220 | },
221 | "platform-dev": []
222 | }
223 |
--------------------------------------------------------------------------------
/application/socketio/controller/Server.php:
--------------------------------------------------------------------------------
1 | saveMsg = Config::get('param.save_msg');
31 | }
32 |
33 |
34 | public function index()
35 | {
36 | $port = Config::get('param.ws.port');
37 | $io = new SocketIO($port);
38 | $io->on('connection', function ($socket) use ($io) {
39 | $socket->on('chat message', function ($msg) use ($io) {
40 | $io->emit('chat message', $msg);
41 | });
42 |
43 | $all = [
44 | 'usersNum' => $this->usersNum,
45 | 'currentUsers' => $this->users,
46 | ];
47 |
48 | $io->emit('sendMsg', json_encode($all, 256));
49 |
50 | echo 'new connection' . PHP_EOL;
51 |
52 | // 监听客户端连接成功发送数据
53 | $socket->on('success', function ($msg) use ($io, $socket) {
54 | $username = $msg['username'] ?: '';
55 |
56 | if (empty($username)) {
57 | $username = str_rand(12);
58 | }
59 | // 将当前客户端加入以他的用户名定义的group
60 | $socket->join($username);
61 | $socket->username = $username;
62 |
63 | // 记录用户,同一个用户打开多个页面算一个,记录页面数量
64 | if (!isset($this->users[$username])) {
65 | $this->users[$username] = 1;
66 | ++$this->usersNum;
67 | // 加入了聊天
68 | $bc = [
69 | 'msg' => $username . ' join the chat',
70 | 'type' => 'join',
71 | 'usersNum' => $this->usersNum,
72 | 'currentUsers' => $this->users,
73 | ];
74 |
75 | $io->emit('sendMsg', json_encode($bc, 256));
76 | } else {
77 | ++$this->users[$username];
78 | }
79 |
80 | $res = [
81 | 'username' => $username,
82 | 'msg' => 'success',
83 | 'usersNum' => $this->usersNum,
84 | 'currentUsers' => $this->users,
85 | ];
86 | $socket->emit('success', json_encode($res, 256));
87 | echo date('Y-m-d H:i:s') . " $username join" . PHP_EOL;
88 | });
89 |
90 |
91 | $socket->on('sendMsg', function ($msg) use ($io, $socket) {
92 |
93 | echo date('Y-m-d H:i:s') . " 收到广播消息:" . json_encode($msg, 256) . PHP_EOL;
94 |
95 | // 向所有客户端广播发送消息 *** SAY
96 | $bc = [
97 | 'msg' => $msg['msg'],
98 | 'from' => $msg['username'],
99 | 'type' => 'say',
100 | ];
101 |
102 | $io->emit('sendMsg', json_encode($bc, 256));
103 |
104 | // 向以用户名定义的组推送消息,达到一对一的推送的效果
105 | // $io->to($msg['username'])->emit('sendMsg', json_encode($response, JSON_UNESCAPED_UNICODE));
106 |
107 | // 向当前客户端推送消息
108 | // $socket->emit('sendMsg', json_encode($response));
109 |
110 | // 不需要存储公频消息注释这句
111 | $data = [
112 | 'msg' => $msg['msg'],
113 | 'from' => $msg['username'],
114 | 'to' => '',
115 | 'type' => 'public'
116 | ];
117 |
118 | if ($this->saveMsg) {
119 | try {
120 | $this->insertMsg($data);
121 | } catch (\Exception $e) {
122 | echo "消息入库失败: " . $e->getMessage() . PHP_EOL;
123 | }
124 | }
125 |
126 |
127 | });
128 |
129 | // 一对一私聊
130 | $socket->on('private chat', function ($msg) use ($io, $socket) {
131 |
132 | echo date('Y-m-d H:i:s') . " 收到私聊消息:" . json_encode($msg, 256) . PHP_EOL;
133 |
134 | if (!empty($msg['to']) && !empty($msg['from'])) {
135 |
136 | $io->to($msg['to'])->emit('private chat', json_encode($msg, 256));
137 |
138 | if ($this->saveMsg) {
139 | try {
140 | $this->insertMsg($msg);
141 | } catch (DbException $e) {
142 | echo "消息入库失败: " . $e->getMessage() . PHP_EOL;
143 | }
144 | }
145 |
146 | }
147 | });
148 |
149 | // 关闭页面/离开聊天室
150 | $socket->on('disconnect', function () use ($socket) {
151 | if (!isset($this->users[$socket->username])) {
152 | $this->users[$socket->username] = 0;
153 | }
154 | --$this->users[$socket->username];
155 | if ($this->users[$socket->username] <= 0) {
156 | echo $socket->username . ' disconnect' . PHP_EOL;
157 | unset($this->users[$socket->username]);
158 | --$this->usersNum;
159 | $socket->leave($socket->username);
160 | $res = [
161 | 'username' => $socket->username,
162 | 'usersNum' => $this->usersNum,
163 | 'currentUsers' => $this->users,
164 | 'type' => 'left',
165 | ];
166 | $socket->broadcast->emit('sendMsg', json_encode($res, 256));
167 | echo date('Y-m-d H:i:s') . " {$socket->username} leave" . PHP_EOL;
168 | }
169 | });
170 |
171 | $socket->on('changeName', function ($msg) use ($io, $socket) {
172 |
173 | $username = $msg['username'] ?: '';
174 | --$this->usersNum;
175 | $socket->leave($username);
176 | unset($this->users[$username]);
177 | echo $username . ' disconnect' . PHP_EOL;
178 | $res = [
179 | 'username' => $username,
180 | 'usersNum' => $this->usersNum,
181 | 'currentUsers' => $this->users,
182 | 'type' => 'left',
183 | ];
184 | $io->emit('sendMsg', json_encode($res, 256));
185 | });
186 |
187 |
188 | });
189 |
190 | // 当$io启动后监听一个http端口,通过这个端口可以给任意user或者所有user推送数据
191 | $io->on('workerStart', function () use ($io) {
192 | // 监听一个http端口
193 | $api_url = Config::get('param.ws.apiHost');
194 | $inner_http_worker = new Worker($api_url);
195 | // 当http客户端发来数据时触发
196 | $inner_http_worker->onMessage = function ($http_connection, $data) use ($io) {
197 | $params = $_POST ? $_POST : $_GET;
198 | // 推送数据的url格式 type=publish&to=user&content=xxxx
199 | switch (@$params['type']) {
200 | case 'publish':
201 | $to = @$params['to'];
202 | // 有指定user则向user所在socket组发送数据
203 | $msg = [
204 | 'msg' => $params['content'],
205 | 'from' => 'system',
206 | 'type' => 'system',
207 | ];
208 | echo date('Y-m-d H:i:s') . " api收到推送消息:" . json_encode($msg, 256) . PHP_EOL;
209 | if ($to) {
210 | $msg['to'] = $to ?: '';
211 | if (isset($this->users[$to])) {
212 | $io->to($to)->emit('sendMsg', json_encode($msg, 256));
213 | } else {
214 | return $http_connection->send($to . 'is offline');
215 | }
216 | } else {
217 | $io->emit('sendMsg', json_encode($msg, 256));
218 | }
219 |
220 | if ($this->saveMsg) {
221 | try {
222 | $this->insertMsg($msg);
223 | return $http_connection->send('ok');
224 | } catch (DbException $e) {
225 | echo "消息入库失败: " . $e->getMessage() . PHP_EOL;
226 | return $http_connection->send('fail');
227 | }
228 | } else {
229 | return $http_connection->send('ok');
230 | }
231 | }
232 | return $http_connection->send('fail');
233 | };
234 | // 执行监听
235 | $inner_http_worker->listen();
236 | });
237 |
238 | Worker::runAll();
239 | }
240 |
241 |
242 | private function insertMsg($data)
243 | {
244 | Db::name('msg')->insert($data);
245 | }
246 | }
--------------------------------------------------------------------------------