在 PHP 7.4 中报错:ErrorException array_key_exists() expects parameter 2 to be array, int given

1、在 PHP 7.4 中报错:ErrorException array_key_exists() expects parameter 2 to be array, int given。如图1

图1

2、代码实现如下,原因为 require($this->getCachePath()) 返回 1,返回 1 的根源在于 路径 $this->getCachePath() 所表示的文件中的内容为空。

if (array_key_exists($path, $this->assetEntries)) {
 return $this->assetEntries[$path];
}

if (!$this->isThemeUpdated()) {
 $this->assetEntries = require($this->getCachePath());

 return;
}
$code = '<?php';
$code .= "\n\n";
$code .= 'return ' . var_export($assets, true) . ';';

$this->local->put($this->getCachePath(), $code, true);


3、其实,当使用 require 时,它是一个语句,而不是一个函数,因此,require($this->getCachePath()) 可以替换为 require $this->getCachePath()

4、参考:include ,$bar 的值为 1 是因为 include 成功运行了。注意以上例子中的区别。第一个在被包含的文件中用了 return 而另一个没有。如果文件不能被包含,则返回 false 并发出一个 E_WARNING 警告。如图2

图2

5、那么推测其原因在于包含文件中的内容虽然预期是 return Array() ,但是实际上其文件中的内容并非如此。因为文件中的内容是基于 $this->local->put($this->getCachePath(), $code, true); 写入的。

6、模拟一下代码的实际运行情况,require 会返回 Array() 的情况。

return.php

<?php

return [
 'a' => 1,
 'b' => 2
];

?>

require.php

<?php

var_dump(require('return.php'));

?>

array(2) {
  ["a"]=>
  int(1)
  ["b"]=>
  int(2)
}

7、模拟一下代码的实际运行情况,require 会返回 1 的情况(一),包含文件中返回 数字 1。

return.php

<?php

return 1;

?>

require.php

<?php

var_dump(require('return.php'));

?>


int(1)


8、模拟一下代码的实际运行情况,require 会返回 1 的情况(二),包含文件中 PHP 标签内的内容为空。

return.php

<?php

?>

require.php

<?php

var_dump(require('return.php'));

?>


int(1)


9、模拟一下代码的实际运行情况,require 会返回 1 的情况(三),包含文件中的内容为空,其为空白文件。

return.php

 

require.php

<?php

var_dump(require('return.php'));

?>


int(1)


10、在生产环境中,require($this->getCachePath()) 返回 1 的情况,则属于 require 会返回 1 的情况(三),包含文件中的内容为空,其为空白文件。

11、查看 Illuminate\Filesystem\Filesystem 中的 put() 方法实现

    public function put($path, $contents, $lock = false)
    {
        return file_put_contents($path, $contents, $lock ? LOCK_EX : 0);
    }

12、具体排查分析流程可参考:当在 PHP 7.4 中使用 file_put_contents() 时,文件内容为空的排查分析

永夜