Download the PHP package jx3dev/jx3dev-php without Composer
On this page you can find all versions of the php package jx3dev/jx3dev-php. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Informations about the package jx3dev-php
jx3dev-php
jx3dev 接口服务的 PHP SDK。HTTP 与 WebSocket 双通道,零运行时依赖——只用
ext-curl、ext-json、ext-openssl,不引入任何框架。
安装
要求 PHP 8.1+。
初始化
令牌只在这里接收一次,之后 HTTP 与 WebSocket 两条通道都会自动携带。只有令牌是必填的:
请求前缀默认 /api/,绝大多数接口都在这里,不用配。少数在别的前缀下的接口见切换前缀。
要调的话,常用的几个(全部选项见下方折叠表):
令牌是否有效由服务端判定。无效或不存在的令牌不会导致连接失败,问题要到第一次调接口时才以权限错误的形式暴露。
服务地址不传则连官方生产环境(Config::DEFAULT_BASE_URI)。测试环境或私有部署必须显式传入第二个参数——忘了传会静默连到生产
,这是全包唯一一处带环境含义的默认值:
令牌请从环境变量或配置文件读取。不要硬编码在代码里,示例代码里也不要出现真令牌。
全部可选项
| 键 | 默认 | 说明 | |----------------------------------------------------------------------|---------------------------------------|-----------------------------------------| | `prefix` | `/api/` | HTTP 请求前缀 | | `ws_uri` | 由 `base_uri` 推导 | WebSocket 完整地址,必须 `ws://` 或 `wss://` 开头 | | `ws_path` | `/ws/` | 推导时拼接的路径 | | `timeout` | `10.0` | 单次请求 / 单次应答等待的超时秒数 | | `connect_timeout` | `5.0` | 建立连接的超时秒数 | | `locale` | 不发送 | `zh_CN` 或 `en` | | `verify_tls` | `true` | 是否校验 TLS 证书 | | `ping_interval` | `120.0` | WebSocket 保活间隔,`0` 表示不自动发 | | `auto_reconnect` | `false` | 是否自动重连 | | `reconnect_on_kick` | `false` | 收到 `event 1001` 后是否仍然重连 | | `backoff_base` / `backoff_max` / `backoff_factor` / `backoff_jitter` | `1.0` / `60.0` / `2.0` / `0.2` | 重连退避 | | `max_reconnect_attempts` | `0`(不限) | 连续失败多少次后放弃 | | `ws_token_in_query` | `false` | 令牌改放握手 query,见下方警告 | | `user_agent` | `jx3dev-php/{版本}`,见 `Config::VERSION` | 服务端识别客户端版本的依据,一般不用改 | 拼错的键会直接报错,不会静默生效为默认值。 > **`ws_token_in_query` 会把令牌写进 URL。** 代价是它随后会出现在反向代理和服务端的**访问日志** > 里,而日志的留存和权限通常不按密钥对待。只有在反代确实会剥离自定义请求头、拿不到 `Authorization` 时才打开它,并且要清楚日志里从此有一份明文令牌。HTTP 调用
统一走 POST + JSON + op 参数式,令牌走 Authorization: Bearer 请求头。
op / token / locale 由 SDK 填充,业务参数里出现同名键会直接报错,不会被静默覆盖。
切换前缀
默认前缀是 /api/,在初始化时定。若文档里某个接口另有前缀,单次调用可以临时切:
按前缀缓存通道,全部共用同一个传输实例——切前缀不会另开连接,默认前缀也不受影响。
前缀必须以斜杠开头和结尾,否则拼出的请求地址不正确。SDK 会直接报错而不是悄悄替你补——静默修正会让人以为自己写对了。
错误处理
服务端给的 msg / code / extra 一个不落地交给你,SDK 不吞、不加工、不静默重试。
不想用异常控制流就换 tryCall(),业务失败不抛,自己看 code:
异常层次:
用法错误不在这棵树里。 非法的配置项、非法的接口名或 scope,抛的是 SPL 的 InvalidArgumentException ——
那是代码写错了,不是调用失败,不该和「服务端拒了」「网断了」一起兜住。所以 catch (Jx3DevException) 捕不到它,这是故意的:这类错误应该在开发期就炸出来。
WebSocket 连接
一条长连接同时干两件事:收事件和调接口。
握手时读一次令牌记进连接,之后每一帧都不用再带。令牌无效不会握手失败——服务端会把你按游客接进来。
事件订阅
三步缺一不可:登记回调 → connect() → run()。只登记回调收不到任何东西——没有东西在读 socket。顺序也别反,协程模式下
connect() 一返回读协程就开工了,之后再登记可能漏掉最早的几帧。
单 handler:
on()每个事件号、onAny各只保留一个——再次注册会顶掉前一个(后注册的生效)并发一条E_USER_WARNING提示。因此别把on()/onAny放进onOpen回调——重连会反复触发、每次都替换并告警;订阅在connect()前登记一次即可,handler 跨重连保留。
通过 WebSocket 调接口
scope 是帧里原样带上的字段,call() / tryCall() / send() 三个方法都有,默认 default,取值含义见接口文档。限
1–32 位 [A-Za-z0-9_],不合规直接抛 InvalidArgumentException —— 不会静默发出去等服务端报错。
echo 由 SDK 自动分配(同一连接内不重复),应答严格按 echo 对号,绝不按到达次序推断——应答不保证按发送顺序返回。等待应答期间事件回调照常触发,不会积压。
WebSocket 通道不认次数配额,只认时间订阅:没有生效中的时间订阅会拿到
10121。
收帧调度(协程环境必读)
一条 socket 只能有一个执行流在读——两个协程同时 fread 会把帧撕开,症状是随机的 JSON 解析失败。SDK 按运行环境自动选调度策略:
| 环境 | 策略 | 谁在读 socket |
|---|---|---|
| 普通 PHP CLI | InlineLoop |
没有并发,等应答的调用自己边等边读 |
| Swoole 协程 | CoroutineLoop |
connect() 时起一个专职读协程独占 socket,其余协程只挂在各自的等待通道上 |
所以在 Swoole 下可以放心这么写:
出站写入也做了串行化:两个协程同时 call() 时,send 走一把互斥,不会撞上「socket 已被另一个协程占用」。
想显式指定策略(比如在协程里强制用阻塞模式):
自定义调度实现 Jx3Dev\Ws\Loop\LoopInterface 即可。
协程模式下务必注册
onError()。 事件回调抛出的异常会打断读协程,之后run()才会把它抛给你——注册了错误处理器就不会中断收帧。
断开与重连
先看关闭码,再决定重不重连。
| 关闭码 | 怎么回事 | SDK 行为 |
|---|---|---|
1008 |
服务端主动断开,原因在断开前那帧 event 1001 的 data.reason 里 |
默认不重连 |
| 其他 | 网络或服务端异常 | 开了 auto_reconnect 才退避重连 |
reconnect_on_kick 单独设一个参数、且默认关闭,是因为 1008 意味着服务端已经判定这条连接不该再存在(比如同一令牌在别处建立了连接),无脑重连只会两边互踢。
换掉底层传输
默认实现零依赖且是阻塞式的。在 Swoole / Workerman 这类常驻协程环境里,实现对应接口注入即可,SDK 其余部分不用动。
接口覆盖
| 通道 | 覆盖 |
|---|---|
| HTTP | 全部接口 |
| WebSocket | 事件订阅 + 接口调用 |
每个接口都能调。是否类型化按需决定——值得封装的手写成真方法、返回对象(如 getTokenStatus() →
TokenStatus);其余用驼峰方法(@method 注解 + __call 转发,IDE 按通道补全)或直接 call() 传原名,返回泛用 ApiResponse(->get('a.b') / ->data() 取值):
接口名一律保留文档里的下划线原名,不做改写。
常驻/协程环境注意
- HTTP 每次请求独占一个 curl 句柄。 不要改成复用——
SWOOLE_HOOK_ALL下curl_exec会让出协程,共用句柄会让后来者的curl_setopt_array覆盖掉正在执行的请求,表现为偶发的「响应对不上请求」。 - 一个
WsChannel只持有一条 socket。 多协程共用同一个WsChannel是支持的(见收帧调度)。但要同时 开两条连接(比如两个令牌各连一条),得建两个Jx3Dev实例——ws()每个实例只缓存一个WsChannel。 - 连着的时候不要再调
connect()。 旧 socket 会被顶掉但不会关闭,服务端留一条僵尸连接,第一条连接上未回的call()也等不到回执了。断线重连由tick()自己判断,不用你手动补一次connect()。 Jx3Dev实例可以做容器单例。 HTTP 通道无共享可变状态;WS 通道的并发安全由调度策略保证。
测试
另有一个不依赖 composer、不联网的自检脚本,用于换环境时快速确认(尤其是没装 PHPUnit 的机器):
它覆盖 PHPUnit 用例之外的两处:真 socket 组帧(stream_socket_pair),以及协程调度(装了 ext-swoole 才跑,没装则跳过并提示)。
常驻环境走的是协程路径,换机器部署前值得跑一次。
覆盖 get_token_status 的成功与各类失败路径、WebSocket 连接的成功与失败路径、echo 乱序对号、事件订阅与取消、被踢后不重连。
许可
MIT
All versions of jx3dev-php with dependencies
ext-curl Version *
ext-json Version *
ext-openssl Version *