You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在PHPStan中判断方法参数是否为字面量/标量字符串(含拼接)

解决方案

要实现只允许纯字符串字面量拼接的参数校验,核心是递归检查拼接表达式的每一部分,确保所有参与拼接的都是标量字符串,不包含变量、常量、函数调用等非标量内容。

修改后的完整代码如下:

<?php

final class StringArgumentOnlyRule implements Rule
{
    public function getNodeType(): string
    {
        return MethodCall::class;
    }

    public function processNode(Node $node, Scope $scope): array
    {
        $allArgs = $node->getArgs();
        $firstArg = reset($allArgs);
        
        // 检查第一个参数是否为纯字符串字面量或其合法拼接
        if ($this->isPureStringConcat($firstArg->value)) {
            return [];
        }

        return ['Must be a string (only scalar literals or their concatenation allowed).'];
    }

    /**
     * 递归验证表达式是否为纯字符串字面量或合法的字符串拼接
     */
    private function isPureStringConcat(Node $expr): bool
    {
        // 情况1:本身就是标量字符串
        if ($expr instanceof Scalar_String) {
            return true;
        }

        // 情况2:是字符串拼接操作,递归检查左右两边
        if ($expr instanceof Expr_BinaryOp_Concat) {
            return $this->isPureStringConcat($expr->left) && $this->isPureStringConcat($expr->right);
        }

        // 其他情况(变量、常量、函数调用等)都不合法
        return false;
    }
}

关键逻辑说明

  1. 递归校验函数:isPureStringConcat 会逐层拆解拼接表达式:
    • 如果当前节点是Scalar_String(纯字符串字面量),直接返回合法;
    • 如果是Expr_BinaryOp_Concat(字符串拼接操作),则递归检查左右两个子表达式是否都合法;
    • 任何其他类型的节点(比如Expr_Variable变量、Expr_ConstFetch常量、Expr_FuncCall函数调用)都会返回不合法。
  2. 主逻辑修改:原来的代码只判断单个标量字符串,现在替换为调用递归函数,覆盖了多段字符串拼接的场景。

这样就能满足需求:允许'a' . 'b' . 'c'这类纯字面量拼接,但拒绝'a' . $var、sprintf('a')、CONSTANT . 'b'等包含非标量内容的情况。

内容的提问来源于stack exchange,提问作者TravisCarden

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 11:02:21