preg_match 无法安全提取 graphql 变量声明,仅能粗略匹配 $ 开头的标识符;必须用 /\$w+/s 排除字符串和注释干扰,但无法处理类型、嵌套或转义;变量应来自受控上下文并白名单过滤,而非正则推断。

preg_match 怎么安全提取 GraphQL query 字符串中的变量声明
PHP 正则无法“解析” GraphQL 语法,但可以粗略提取 query 块内以 $ 开头、后跟字母/数字/下划线的变量名(如 $id、$slug),前提是字符串结构规整。不要指望它识别嵌套或类型注解。
常见错误现象:用 /$w+/ 直接匹配,结果把注释里的 $id、字符串字面量里的 "$id" 甚至字段名 user$id 全部抓出来;或者遇到换行、空格缩进就失效。
- 必须加
s修饰符(/$w+/s)让.匹配换行符,否则跨行的query { ... }会断掉 - 用
(? 排除双引号包围的场景,但无法覆盖转义引号或单引号字符串,仅作基础过滤 - 若需区分
$slug: String!和$slug(无类型),正则基本不可靠——GraphQL 类型定义是语法层,不是文本模式
为什么不能靠 preg_match 来校验或生成 variables 数组
GraphQL 变量声明和实际传入的 variables 是分离的:查询字符串里写 query GetUser($id: ID!) {...},不代表 PHP 就该自动从这个字符串里抽 ['id' => ...] 并填充。这样做既不安全也不健壮。
真实使用场景中,variables 应来自受控上下文(如已验证的请求参数、数据库查出的值),而非从用户提交的 query 字符串里“猜”。否则攻击者可构造恶意 query 注入任意变量名,绕过类型约束。
-
preg_match_all('/$(w+)/', $raw_query, $matches)抽出变量名列表,只是调试辅助,不能直接用于构建variables数组 - 若 query 中有
@autodeclare(如 graphql.js 的扩展),那更不能靠 PHP 正则识别——那是客户端运行时行为,PHP 端根本看不到该注解语义 - webonyx/graphql-php 在执行前会做完整 AST 解析和变量校验,
preg_match提前做的任何“推断”都可能与最终解析结果不一致
真正要兼容变量,得在 GraphQL 执行层处理
PHP 端真正需要“兼容变量”的地方,是调用 GraphQLGraphQL::executeQuery() 时传入正确的 $variables 参数。这和正则完全无关,而是数据流向控制问题。
典型错误:前端发来 {"query":"query GetPost($slug:String!) {...}", "variables":{"slug":"hello"}},后端却用 $_POST['query'] 拼接出新字符串再丢给 GraphQL 执行器,中间漏了 json_decode($_POST['variables'], true)。
- 始终用
json_decode(file_get_contents('php://input'), true)获取原始请求体,避免 $_POST 自动解析破坏嵌套结构 - 对
$variables做白名单过滤(如只允许['slug', 'id', 'limit']),而不是动态反射 query 字符串里的变量名 - 若 query 中声明了
$slug: String!,但variables里没传slug,GraphQL 执行器会返回标准错误"Variable "$slug" of required type "String!" was not provided",这不是正则能提前拦截的
复杂点在于混合场景:带内联变量的字符串拼接
当 PHP 不走标准 variables 传参,而用双引号拼接(如 "{ post(id: "$slug") { title } }"),此时变量是否合法,取决于 $slug 的内容是否被正确转义——这和正则无关,但容易被忽略。
例如 $slug = 'my-post" or true'; 直接插进去会导致 GraphQL 解析失败,甚至暴露服务端错误细节。
- 永远不用
preg_quote()处理 GraphQL 字符串插值——它针对 PCRE,不是 GraphQL 字符串规则 - 正确做法是:对每个变量值,手动包裹双引号 + 转义内部双引号(
str_replace('"', '\"', $value)),再拼入查询字符串 - 更稳妥的是彻底放弃字符串拼接,改用标准
variables方式,哪怕多写两行代码
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











