【问题标题】:PHP Array/objects passed as reference being created when unset?未设置时作为引用传递的PHP数组/对象?
【发布时间】:2017-09-07 08:55:00
【问题描述】:

我有一个小函数可以从数组/对象中获取元素值:

<?php
function element( $ind, &$var, $def = NULL ) {
    echo "inside: ".json_encode(isset($var) ? $var : '<unset>') . PHP_EOL;
    if (isset($var) && is_array($var)) {
        return empty($var[$ind]) ? $def : $var[$ind];
    }
    if (isset($var) && is_object($var)) {
        return empty($var->{$ind}) ? $def : $var->{$ind};
    }
    return $def;
}

echo "var before: ".json_encode(isset($myvar) ? $myvar : '<unset>') . PHP_EOL;
$value = element( 'zz', $myvar, '' );
echo "var after: ".json_encode(isset($myvar) ? $myvar : '<unset>') . PHP_EOL;
echo PHP_EOL;
echo "array before: ".json_encode(isset($myarray) ? $myarray : '<unset>') . PHP_EOL;
$value = element( 'zz', $myarray['yy'], '' );
echo "array after: ".json_encode(isset($myarray) ? $myarray : '<unset>') . PHP_EOL;
echo PHP_EOL;
echo "object before: ".json_encode(isset($myobject) ? $myobject : '<unset>') . PHP_EOL;
$value = element( 'zz', $myobject['yy'], '' );
echo "object after: ".json_encode(isset($myobject) ? $myobject : '<unset>') . PHP_EOL;

我的问题是,如果传递的$var 是一个数组或一个对象,但实际上没有设置,那么它会被神奇地创建,从而导致问题:

$ php z.php
var before: "<unset>"
inside: "<unset>"
var after: "<unset>"

array before: "<unset>"
inside: "<unset>"
array after: {"yy":null}

object before: "<unset>"
inside: "<unset>"
object after: {"yy":null}

知道为什么会发生这种情况以及如何预防吗?

编辑

好的,我收到了很多“不要那样做”和“告诉别人做某事”的说法,所以我将解释更多的情况。我有超过 300,000 行 PHP 代码的代码库,多年来一直使用 element() 函数从各种变量中获取值(在 800 多个地方调用),现在突然间出现了一些由于函数神奇地创建了不存在的变量而导致的问题。具体的例子是,有一个非常大的多维数组$member 被这样传递:

<?php echo json_encode(element('base_name', $member[$wizard_type], ''); ?>

目前尚不清楚$member[xxx] 在任何给定情况下会有哪些元素,显然在某些情况下它没有设置,在这种情况下,只使用空字符串(第三个参数)就可以了。不幸的是,这个调用实际上设置 $member[$wizard_type],然后代码会因此而被执行,这是不应该的。

如果我可以从element() 函数中删除引用并以某种方式抑制错误,那我想就可以了。

【问题讨论】:

    标签: php arrays object pass-by-reference


    【解决方案1】:

    手册中有解释: http://php.net/manual/en/language.references.whatdo.php

    注意: 如果您通过引用分配、传递或返回未定义的变量,它将被创建。

    所以

    知道 [...] 如何预防吗?

    不要作为参考传递。

    没有办法阻止这种行为。您必须重构代码以确保给出的结果符合您的预期。

    【讨论】:

    • 当我不作为参考传递时,会出现错误,但我不希望调用者在每次调用时都必须加上“@”,有没有办法防止错误在element 函数内部?
    • 这是因为您的变量从未创建或声明过。这是一个常见的错误。您应该防止这种情况并且不要抑制错误。
    • 我无法控制这些元素的存在,或者即使它是一个对象或一个数组,这就是函数的目的——处理所有情况。
    • 函数的目的是接收一个值(或不接收),处理并返回(或不)。但是,确保向函数提供值是程序员/开发人员的责任。所以,这样做if(isset($myVar)) { myFunction($myVar); } 而不是试图阻止 PHP Core 的常见行为。
    • 我看到现在没有办法解决我的问题,这个函数不应该以这种方式使用。这是正确的答案,我接受它,现在继续数周重写其他人的代码。谢谢大家。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-17
    相关资源
    最近更新 更多