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

PHP可变变量操作数组/对象失效,Twig自定义函数赋值失败

问题分析

你的核心问题有两个:

  1. 值传递而非引用传递:代码中$array = $originalArray;是值拷贝,后续修改的是副本,原对象/数组根本没被改动,返回的副本也因为可变变量的逻辑错误没正确赋值。
  2. 可变变量的动态赋值逻辑不可靠:通过拼接字符串生成变量访问路径的方式,无法正确处理数组与对象混合的嵌套结构,且语法上存在隐患。
解决方案

替换掉可变变量的写法,改用循环遍历键路径的方式,同时处理引用传递(对象默认是引用,数组需要显式引用),兼容数组和公共对象的混合嵌套,还能自动创建不存在的中间节点。

修正后的PHP实现

/**
 * 向数组/公共对象中精准赋值,替代Twig的merge方法
 *
 * @param array|object $target 要赋值的目标数组或公共访问对象
 * @param mixed $value 要设置的值
 * @param string ...$keys 嵌套的键路径(前缀array_表示数组键,否则为对象属性)
 * @return array|object 修改后的目标
 */
public function arrayKeyValueSetter($target, $value, ...$keys)
{
    // 处理数组的引用传递,对象默认是引用类型
    $current = is_array($target) ? &$target : $target;

    foreach ($keys as $index => $key) {
        // 判断当前键是数组键还是对象属性
        $isArrayKey = str_starts_with($key, 'array_');
        $realKey = $isArrayKey ? substr($key, 6) : $key;

        // 如果是最后一个键,直接赋值
        if ($index === count($keys) - 1) {
            if ($isArrayKey) {
                $current[$realKey] = $value;
            } else {
                $current->$realKey = $value;
            }
            break;
        }

        // 自动创建不存在的中间节点
        if ($isArrayKey) {
            if (!isset($current[$realKey]) || !is_array($current[$realKey])) {
                $current[$realKey] = [];
            }
            $current = &$current[$realKey];
        } else {
            if (!isset($current->$realKey) || !is_object($current->$realKey)) {
                $current->$realKey = new stdClass();
            }
            $current = $current->$realKey;
        }
    }

    return $target;
}

关键改进点

  • 引用处理:数组使用&实现引用传递,确保修改的是原数组;对象本身是引用类型,无需额外处理。
  • 键路径遍历:通过循环逐个处理嵌套键,避免可变变量的语法陷阱。
  • 自动创建中间节点:如果嵌套路径中的某个节点不存在,自动创建数组或空对象,避免报错。
  • 灵活参数:使用可变参数...$keys替代多个固定参数,支持任意深度的嵌套。

Twig调用调整

改用可变参数后,直接按顺序传递键路径即可:

{% if value is defined and value is not null %}
    {% set form = form|array_key_value_setter(value.id, 'children', 'array_media', 'vars', 'array_contentHasMediaId') %}
{% endif %}

验证结果

现在调用dump(form.children.media.vars.contentHasMediaId)会正确输出你设置的value.id值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 14:52:17