【问题标题】:Dealing with PHP 8.1 warning for undefined array key处理未定义数组键的 PHP 8.1 警告
【发布时间】:2022-10-13 15:49:10
【问题描述】:

我们正在升级到 PHP 8.1。一个新功能是未定义的数组键会引发警告。

不幸的是,这会干扰轻松使用关联数组(例如 $_SESSION 变量)的能力。我了解预定义变量的优点,我不是在寻找关于这些优点的讨论。关联数组的想法是您可以轻松地将内容添加到会话中,并且所有未分配的内容都被评估为空。但现在它也发出警告;必须采取一些措施来解决这个问题。

这是一些代码的示例:

$_SESSION['is_condition'] = true;

在代码的另一个地方,出现以下情况

if ($_SESSION['is_condition']) ...

如果这发生在未定义“is_condition”会话变量的上下文中,则将其值评估为 null 的预期结果就是我们想要的。但是现在必须做其他事情来处理它未定义的可能性。

有几种方法可以解决这个问题:

  1. 预定义所有值为 null 的会话变量。似乎它不是关联数组的精神。现在每个脚本都必须调用一组冗长的代码。

  2. 每当需要关联数组元素的值时,请使用空合并运算符。在整个代码库中放置许多额外的运算符是一个丑陋的要求。

  3. 更改我们的自定义错误处理函数以忽略未定义的数组键错误。抑制警告并增加开销是一个非常糟糕的主意。

    这些方法都不是非常理想的。

    解决此问题的一种理论方法是使用数组初始化语句,将所有可能的关联键分配给 null。我不知道有这样的事情。

    我的问题是我是否缺少其他一些方法,例如仅抑制此特定警告的参数。

【问题讨论】:

  • 您还可以使用issetarray_key_exists!empty
  • 未定义的数组索引总是触发警告。我认为它简单地从E_NOTICE 更改为E_WARNING
  • 大多数应用程序没有很多有条件分配的会话变量,因此您不必在很多地方处理这个问题。对于您所做的那些变量,空合并运算符是最简单的解决方案。
  • 这回答了你的问题了吗? Best way to handle Undefined array key in PHP 8.0

标签: php undefined associative-array php-8.1


【解决方案1】:

我的建议是在处理这个问题的会话机制上写一个抽象。我会选择一个类,但即使是一个简单的函数也可以工作:

function getValueFromSession(string $key, mixed $defaultValue = null) : mixed
{
   return isset($_SESSION[$key]) ? $_SESSION[$key] : $defaultValue;
}

这有一个额外的好处,即允许您更改底层会话存储(例如到 Redis),而无需更改会话值访问的每个实例。

【讨论】:

  • 虽然我通常喜欢这种方法,但它的缺点是在需要值时调用函数调用。例如,某些会话变量在单个脚本中被访问数十次。所以你必须为所有这些事件调用该函数。
  • @JeffreySimon,您不会真的要这样做。它不是特别昂贵,而且是干净、简洁、理智的代码。
【解决方案2】:

由于 php8 isset 已更改并且对未定义键的访问会引发警告。您应该使用array_key_exists 方法。

$_SESSION['a'] = array_key_exists('a', $_SESSION) ? $_SESSION['a'] : null;

【讨论】:

    【解决方案3】:

    您假设$_SESSION['whatever'] 始终可用。您可以使用 isset 包装所有条件,如下所示:

    if (isset($_SESSION['is_condition'])) {
    //Do Whatever
    }
    

    或者你可以做一些笨拙的事情,比如把它放在文件的顶部。

    if (isset($_SESSION['is_condition'])) {
    //Do something
    } else {
    $_SESSION['is_condition'] = NULL;
    } 
    

    从那时起,任何时候你检查会话中的那个键,它至少会被设置为某些东西,并且不会发出警告或通知。这很丑陋,但它会起作用。

    【讨论】:

    • 请注意,只要会话变量中有值,这些 if 块就会执行,即使该值是false。使用if (isset($_SESSION['var']) && $_SESSION['var']) 来防止。
    • 第一个建议在某些情况下会起作用,实际上我们有时会使用它,但对于像下面这样的结构,它会很笨拙: if ($_SESSION['a'] || $_SESION['b']) .... 那是因为在某些情况下可能有 20 个或更多这样的条件。第二个建议是丑陋的,但实际上是我们现在正在做的。但是,语法糖如下: $_SESSION['a'] = $_SESSION['a'] ??无效的;
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-07-01
    • 1970-01-01
    • 2022-11-07
    • 2013-05-16
    • 1970-01-01
    • 2022-01-15
    • 2021-12-20
    相关资源
    最近更新 更多