Webman连接Dgraph需用Guzzle发送HTTP请求至其/query或/mutate端点,不可配置进database.php;须用GraphQL+-语法构造JSON-RPC请求,注意谓词大小写、UID格式及Content-Type头。

Webman里怎么连Dgraph而不是MySQL
Webman本身不内置图数据库支持,Dgraph 是独立的 HTTP/gRPC 服务,不能像 Db::connection('mysql') 那样直接配置进 config/database.php。必须用 HTTP 客户端手动对接,推荐用 guzzlehttp/guzzle 或原生 cURL 发送 JSON-RPC 请求。
常见错误是试图把 Dgraph 当作传统关系型数据库来“配置连接”,结果在 Db::connection('dgraph') 上直接报 Class not found —— 因为 Webman 的 illuminate/database 根本不识别 dgraph 驱动。
- 安装客户端:
composer require guzzlehttp/guzzle - Dgraph 默认监听
http://127.0.0.1:8080(不是 3306),所有读写都走/query和/mutate端点 - 不要往
config/database.php的connections数组里加'dgraph' => [...],这毫无作用 - 若需复用连接,建议封装成单例服务类(如
DgraphClient),避免每次请求新建GuzzleHttp\Client
怎么发GraphQL+-查询到Dgraph
Dgraph 使用自研的 GraphQL+- 语法,不是标准 GraphQL。Webman 中调用时必须严格按其格式构造 JSON 请求体,否则返回 parse error 或空结果。
例如查所有带 name 谓词的节点,不能写成 SQL 式的 SELECT * FROM ...,也不能套用 Eloquent 的 where() 链式调用。
- 正确示例(HTTP POST 到
/query):{ "query": "{ all(func: has(name)) { uid name age } }" } - 错误写法:
Db::table('person')->where('name', 'like', '%John%')->get()—— 这会直接报错,Db不认识person表,Dgraph 也没有表概念 - 参数必须用变量绑定(
$var),不能拼字符串,否则有注入风险;例如:"query": "query($a: string) { all(func: eq(name, $a)) { uid } }", "variables": { "$a": "Alice" } - 返回是纯 JSON,结构固定为
{"data": {...}},需手动解码:json_decode($response->getBody(), true)['data']
突变(Mutate)失败的典型原因
Dgraph 的 /mutate 接口对数据格式极其敏感,一个字段名大小写错误、少个逗号、UID 类型写成字符串,都会导致整个突变失败并返回 error 字段。
Webman 2.2.0版本强化了 TCP/UDP 服务支持,优化路由组管理,并增强异步任务处理能力。结合协程与连接池技术,Webman 能轻松应对高并发场景,适用于网站、接口服务、即时通讯、物联网及游戏开发,兼具高性能、灵活扩展与稳定可靠,是多场景 PHP 服务开发的理想选择。
最常踩的坑是把谓词(predicate)当成 MySQL 字段来设计:Dgraph 中 name、age 是全局谓词,不是某张表的列;且 uid 必须是十六进制字符串(如 "0x1"),不能是整数或 UUID。
- 成功突变示例:
{ "set": [{ "name": "Alice", "age": 30 }] } - 失败场景:
-
"age": "30"(字符串 → 应为整数) -
"Name": "Alice"(大小写错,谓词名区分大小写) - 漏掉外层
"set"键,直接传数组 - 没设
Content-Type: application/json请求头
-
- 突变后若要立即查新数据,需加
"commitNow": true,否则可能因事务延迟看不到
Webman中间件里怎么安全透传Dgraph上下文
不能在中间件里全局设置 DgraphClient 实例或复用未清理的连接句柄。Dgraph 没有连接池概念,每个请求都是无状态 HTTP 调用,但错误复用 GuzzleHttp\Client 可能导致 DNS 缓存、TCP 复用异常或超时堆积。
尤其要注意 Guzzle 的 handler 配置 —— 默认使用 StreamHandler,在 Worker 长期运行下容易积累 socket 资源;生产环境务必换成 CurlMultiHandler 并设 max_handles。
- 推荐做法:在中间件中只做请求预处理(如提取 JWT 中的 tenant ID),不初始化客户端;真正调用放在 Controller 或 Service 层
- 若需跨请求传递上下文(如租户隔离),用
context包或DI\Container注入,别用全局变量或静态属性 - 错误示范:
static $client = new Client();—— 会共享 cookie、header、timeout 设置,不同租户请求互相污染 - 调试时可在响应头加
X-Dgraph-Request-ID,方便追踪日志
Dgraph 的谓词类型和索引规则必须提前定义好再写入数据,动态改 schema 会阻塞写入;这点和 MySQL 的 ALTER TABLE 完全不同,容易被忽略。

















