当我将空值视为这样的数组时,为啥 PHP 不会抱怨?

Posted

技术标签:

【中文标题】当我将空值视为这样的数组时,为啥 PHP 不会抱怨?【英文标题】:Why does PHP not complain when I treat a null value as an array like this?当我将空值视为这样的数组时,为什么 PHP 不会抱怨? 【发布时间】:2014-06-24 07:35:45 【问题描述】:

php 中,我将 error_reporting 设置为报告包括通知在内的所有内容。

为什么以下内容不会引发任何通知、错误或其他任何内容?

$myarray = null;
$myvalue = $myarray['banana'];

故障排除步骤:

$myarray = array();
$myvalue = $myarray['banana'];
// throws a notice, as expected ✔

$myarray = (array)null;
$myvalue = $myarray['banana'];
// throws a notice, as expected ✔

$myarray = null;
$myvalue = $myarray['banana'];
// no notice or warning thrown, $myvalue is now NULL. ✘ Why?

这可能是 PHP 中的一个错误,或者我只是不了解它的工作原理。

【问题讨论】:

就数据类型而言,PHP 并不是真正最合乎逻辑的语言:me.veekun.com/blog/2012/04/09/php-a-fractal-of-bad-design 我同意@Blender 的观点:它通常会做最有意义的事情,尽其所能。这通常非常方便,不会因为小错误而打扰任何人。 哇 - 我已经使用 PHP 多年了,不知何故直到今天才被这种疯狂所困扰。快速测试表明,这种疯狂的设计决定在 PHP 7 中保持不变。:( 您甚至可以这样做:<?php null['banana'];,这不是错误。我想这与使用包含空值的变量相同,但它看起来非常奇怪。和 Mark 一样,我在使用 PHP 几年后才遇到这种情况,我很惊讶。 【参考方案1】:

在以下三种类型中使用数组解除引用语法可能是有效的:

数组 字符串(访问给定位置的字符) 对象(实现 ArrayAccess 接口的对象)

对于所有其他类型,PHP 只返回 未定义变量

数组取消引用由FETCH_DIM_R opcode 处理,它使用zend_fetch_dimension_address_read() 来获取元素。

如您所见,NULL 有一种特殊情况,还有一种默认情况,它们都返回未定义变量

【讨论】:

这是正确的答案,$myarray['banana']的评估没有类型杂耍。【参考方案2】:

通常,当您尝试像使用另一种类型一样使用一种类型的值时,会引发错误或警告,或者发生“类型杂耍”。例如,如果您尝试用. 连接两个数字,它们都会被强制转换为字符串并连接起来。

但是,正如 the manual page about type juggling 中所解释的,当将非数组视为数组时,情况并非如此:

当前未定义自动转换为数组的行为。

实际上,正如您所观察到的,当通过取消引用非数组触发此“未定义行为”时发生的行为是 null 被返回。这不仅会影响空值 - 如果您尝试取消引用数字或资源,您还将获得 null

【讨论】:

谢谢 Narf,之前错过了 Type Juggling 页面的那部分。但是,如果遇到“未定义”的行为,您会认为发出警告或通知对他们来说是一个有用的设计选择。 嗯,我希望 PHP 也更严格一些,但是……这是一种独特的功能,我认为他们不会愿意随时弃用很快。 我不希望他们弃用任何东西,只需发出通知或警告,以便与您访问不存在的数组索引的其他时间保持一致,并警告开发人员注意潜在的错误。 $myarray['banana'] 的评估中没有类型杂耍(通过引用文档在此答案中正确公开)。 PHP 源代码就是证明。解释和链接由this answer提供。【参考方案3】:

从 2006 年开始有一个活跃的bug report。

在文档中,String 部分对此进行了通知。

【讨论】:

太好了。据我所知,当我写这篇文章时,它不在文档中(或者我可能因为它在字符串部分而错过了它),所以感谢添加/提交它的人。 对于 PHP 7.4,现在会抛出通知:wiki.php.net/rfc/notice-for-non-valid-array-container

以上是关于当我将空值视为这样的数组时,为啥 PHP 不会抱怨?的主要内容,如果未能解决你的问题,请参考以下文章

当我将 print_r() 应用于 PHP 中的数组时,为啥会得到“资源 id #4”? [复制]

Laravel - 将空值插入数据库

使用比较对 Kendo Grid JQuery 进行排序 - 排序时将空值放在最后

ssis 空日期作为空值

如何使用 LINQ 将空值发送到 ASP.NET 中的非空列

将空值传递给 SVG 路径(使用 d3.js)以抑制丢失数据