使用Nikic PhpParser修改PHP文件数组变量时新增元素报错如何解决
错误原因
你遇到的报错是因为PhpParser的AST语法树中,所有节点都是对应的类实例对象,不能直接将PHP原生数组插入到$Ex->expr->items数组中:
$Ex->expr->items中存储的每一项都是PhpParser\Node\Expr\ArrayItem类型的对象- 数组的键、值也需要分别构造为对应的标量节点对象,不能直接使用字符串
解决方案
你需要先构造符合PhpParser规范的数组元素节点,再添加到items数组中,示例操作如下:
首先导入需要用到的节点类:
use PhpParser\Node\Expr\ArrayItem; use PhpParser\Node\Scalar\String_;
把你原来新增数组元素的代码替换为:
// 构造新的数组元素节点 $newItem = new ArrayItem( new String_('value3_added'), // 数组值节点 new String_('key_3_added') // 数组键节点 ); // 插入到数组items列表中 $Ex->expr->items[] = $newItem;
现有代码其他可修复点
- 数组值修改逻辑有误:你当前用
$fetItem->value->name->parts[0]修改值是针对常量值的写法,如果你数组的值是字符串字面量,应该直接修改$fetItem->value->value:
switch ($fetItem->key->value) { case 'key1': $fetItem->value->value = "value1_updated"; break; case 'key2': // 按你的预期key2的值不需要修改,可直接删除该分支 break; }
- 补充常量
CONSTANT1和变量$variable1的修改逻辑,完整遍历代码参考:
foreach ($stmts as $item) { if (!property_exists($item, "expr")) continue; $Ex = $item->expr; // 处理define常量修改 if ($Ex instanceof \PhpParser\Node\Expr\FuncCall && $Ex->name->toString() === 'define') { if ($Ex->args[0]->value->value === 'CONSTANT1') { $Ex->args[1]->value = new String_('cons1value_updated'); } } // 处理普通变量赋值修改 if ($Ex instanceof \PhpParser\Node\Expr\Assign) { // 修改$variable1 if ($Ex->var->name === 'variable1') { $Ex->expr->value = 'var1value_updated'; } // 原有的variable2修改逻辑 if ($Ex->var->name === 'variable2') { foreach ($Ex->expr->items as $fetItem) { if ($fetItem->key->value === 'key1') { $fetItem->value->value = "value1_updated"; } } // 新增数组元素 $newItem = new ArrayItem( new String_('value3_added'), new String_('key_3_added') ); $Ex->expr->items[] = $newItem; } } }
修改完成后将AST输出为代码写入目标文件即可:
$newCode = $prettyPrinter->prettyPrintFile($stmts); file_put_contents('first.php', $newCode);
内容的提问来源于stack exchange,提问作者Md Jahid Khan Limon
相关产品推荐
相关产品推荐

