在严格的环境中PHP未定义的变量变量

时间:2017-07-19 17:21:03

标签: php

我的Magento环境设置为error_reporting(E_ALL);,我正在调试一堆警告。

我有一个循环和标记,如下所示:

foreach ( $vars as $key => $value) {
    $value  = is_array($value) ? $value: trim($value);
    ${$key} = ( !empty($value) ? $value: '' );
};
// echo $type; die(); <----- die() shows value correctly
echo $type; // <----- get notices

$fieldType = ( $type == 'money' ? 'number' : 'text' );
echo "<div class=\"input-box {$fieldType}\">";
... rest of code here

我的最终目标是创建一个字符串并将变量抛入其中;所以应该在此之前进行检查。

尝试使用动态创建的变量时,我收到此错误通知Undefined variable: type。如果我echo $type; die();比我得到一个价值就好了。如果我检查get_defined_vars()我在数组中看到了$type变量,所以我知道它就在那里。我只是无法在初始循环内预先设置变量。

我尝试过像${$key} = ( !empty($value) ? $value: 'something' );这样的东西也无济于事。

这是我的var_dump

array(11) {
  ["title"] => string(23) "Name:"
  ["instructions"] => string(0) ""
  ["isrequired"] => string(1) "1"
  ["classnames"] => string(0) ""
  ["defaultval"] => string(0) ""
  ["page"] => string(1) "1"
  ["type"] => string(4) "text"
  ["id"] => string(6) "Field1"
  ["requiredstar"] => string(0) ""
 }

1 个答案:

答案 0 :(得分:0)

你确定总是设置$ type吗?只要$ vars中有一个名为type的密钥,您的代码才会起作用。例如,如果$ vars是一个空数组,则没有type键,您将收到错误。

您也可以尝试设置默认值:

$type = '';
foreach ( $vars as $key => $value) {
    $value  = is_array($value) ? $value: trim($value);
    ${$key} = ( !empty($value) ? $value: '' );
};

$fieldType = ( $type == 'money' ? 'number' : 'text' );

从您的一些评论中,听起来这与API调用有关。我建议你在这里遇到一些代码设计问题。您的代码隐式假定数据应包含名为type的密钥,并且(如所写),如果缺少该密钥,您的程序将遇到错误。你不希望这种情况发生。相反,如果这是API调用的必需参数,则应明确检查其是否存在,然后在缺少API时返回API错误。输入错误不应该导致PHP中的实际错误(或通知)。总是假设有人打算调用你的API错误(或者假设你调用的API会返回错误的数据)。永远不要假设其他人总能完美地完成任务。

处理此问题的另一种方法是简单地将数据保留为数组。您是否有特殊原因试图将此数据数组解压缩为变量?虽然PHP将允许您按变量名称处理变量,但正如您所做的那样(${$key}),它往往会引起混淆,因为现在不再有给定变量与上次初始化时的明确连接/更新。特别是在需要参数的情况下,我认为你最好手动解压缩它:

$type = $vars['type'] ?? '';
if ( !$type )
    // handle error here

编辑再添加一个想法

这个有点延伸,但这是我唯一的想法。我把它作为评论开始,但把它移到我的答案,以便我有更多的空间。

我想知道你是否有编码错误。我们的想法是,如果API以错误的编码返回数据,并且您使用该数据分配给变量,则可能会定义变量,但实际上无法访问该变量,因为PHP内存中的字符集与文本编辑器的字符集不匹配。在其他情况下,我被同样的基本错误所困扰。现实的等价物是当实际名称为零时,用大写的“o”键入变量名。

同样,似乎不太可能,但很容易检查。你应该做的就是忘掉你的foreach循环。无论如何,良好调试的关键是隔离。在进入foreach循环之前,在$vars变量上执行vardump,然后执行以下两行代码:

if ( !isset( $vars['type'] ) )
    throw new \Exception( "Yup, encoding error (or other really weird bug)" );

如果var_dump认为该数组有一个type键,但是isset认为该数组没有type键,那么肯定会有一些时髦的事情发生。但是,如果isset()同意var_dump(),那么我会说你正在处理隐藏在你代码中的更多普通错误。在这种情况下,我认为你最好的下一步是放弃你的foreach循环并使用更明确的数组解包,正如我上面所讨论的那样。