【问题标题】:Getting "Undefined Index" on array created with str_getcsv(); but var_dump() shows key exists在使用 str_getcsv() 创建的数组上获取“未定义索引”;但 var_dump() 显示密钥存在
【发布时间】:2019-07-12 13:41:23
【问题描述】:

我有一个使用 str_getcsv() 创建的数组:

$array = array_map('str_getcsv', file($file['tmp_name']));
array_walk($array, function(&$a) use ($array) {
    $a = array_combine($array[0], $a);
});
array_shift($array);

返回的$arrayvar_dump($array) 输出。

array(18) {
  ["fund"]=>
  string(6) "Fund 1"
  ["name"]=>
  string(13) "Property Name"
  ["investment"]=>
  string(13) "Investment Name"
  ["region"]=>
  string(6) "London"
  ["sector"]=>
  string(6) "Office"
  ["status"]=>
  string(8) "Published"
  ["description"]=>
  string(0) ""
  ["acquisition_date"]=>
  string(0) ""
  ["size"]=>
  string(0) ""
  ["address_line_1"]=>
  string(0) ""
  ["address_line_2"]=>
  string(0) ""
  ["city"]=>
  string(6) "London"
  ["county"]=>
  string(0) ""
  ["postcode"]=>
  string(0) ""
  ["longitude"]=>
  string(0) ""
  ["latitude"]=>
  string(0) ""
  ["featured"]=>
  string(0) ""
  ["external_link"]=>
  string(0) ""
}

当我尝试访问$array['fund']; 时,我得到Notice: Undefined index: fund。我的第一个想法是 fund 在 CSV 标头的键名中有一个隐藏字符,因为 $array['name'] 有效,但我已经检查过,唯一的隐藏字符是 CR LF

我在 StackOverflow 上看到过类似的多维数组问题,但不是单维数组。

任何帮助将不胜感激。我什至尝试过转换为 StdClass 和 $array->fund 并收到关于属性不存在的类似错误。

我尝试将第一个标题列名称重命名为任何名称,但仍然存在问题,所以我想知道访问第一个键是否有问题。

【问题讨论】:

  • Do: $new = []; foreach ($array as $k => $v) { $new[trim($k)] = $v; } before 并检查它是否适用于新数组。它应该删除所有不可见的空格(包括 CR LF)
  • 我试过了,但没有用。但是,我刚刚在 Excel 中打开了 CSV 文件,并使用 Comma Separated Vales (.csv) 选项而不是 file > save as 菜单中的 CSV UTF-8 (Comma Delimited) (.csv) 选项重新保存,它工作正常。我会尝试为遇到此问题的其他人更新答案。
  • 您的文件中可能有 BOM - 请阅读 stackoverflow.com/questions/45240387/…
  • 您需要添加您实际使用的代码,以及有问题的输入文件,至少该行。否则我们只能猜测。

标签: php arrays undefined-index


【解决方案1】:

tldr;

当您应该访问$array[0]['fund'] 时,您正在尝试访问$array['fund']。您将其视为单维数组,但它是一个多维数组(第 1 维,索引;第 2 维,关联)。


解释:

您没有显示您尝试访问 $array['fund'] 的特定代码,也没有显示您的特定输入,但问题似乎是您误解了用于解析 CSV 的代码的结果数组的结构是什么.

array_map() + array_walk() + array_combine() + array_shift() 似乎是一种有点令人困惑的方式来获得你想要的东西,结果正在显示。这是一个明显的例子,说明“聪明”的代码正在提高生产力。两个线性数组结构比一些替代方案更难解析。

我将假设此输入,因为您不提供任何输入并且读取外部文件超出了此问题的范围(并且本身并不是真正的问题):

// input

$lines = <<<EOF
fund,name,investment,region,sector,status,description,acquisition_date,size,address_line_1,address_line_2,city,county,postcode,longitude,latitude,featured,external_link
"Fund 1","Property Name","Investment Name","London","Office","Published","","","","","","London","","","","","",""
EOF;

这与您在问题中显示的数组匹配。

让我们试着剖析代码:

$array = array_map('str_getcsv', explode(PHP_EOL, $lines));

这会为您留下一个包含两个元素的数组。在索引 0 处有标题,在索引 1 处有值。

array_walk($array, function(&$a) use ($array) {
    $a = array_combine($array[0], $a);
});

在这里,您遍历这两个数组中的每一个,array_combine() 每个数组的索引为 0。您希望创建数组,其中键是包含标题的数组中的值 ($array[0])。

注意:这应该清楚地表明 $array 在索引数组中,因为您已经尝试访问位置 0 处的元素。

显然,您最终会得到一个额外的数组(标题数组与标题数组结合),但您稍后会处理。

array_shift($array);

在这里,您摆脱了标题数组(具有像$element['fund'] = 'fund' 这样的值的标题)。您删除了两个元素数组的第一个元素。同样,此操作**仅在 $array 是一个索引数组开始时才有意义。

此时您有一个包含一个元素的数组,该元素是一个包含 18 个键=>值的数组。

如果此时您尝试访问$array['fund'],它自然会失败。因为$array索引数组,而不是关联数组

您需要访问该索引数组的元素,然后尝试访问fund

例如:$array[$i]['fund'];

你可以看到它在工作here

【讨论】:

  • 那么,如果您建议 var_dump($array) 不显示多维数组(而是显示 assoc 数组),那么为什么?
  • Stefan,我看不到您在生成数组后使用的代码,也看不到您正在使用的输入。但是,如果您查看我链接的示例,您会清楚地看到该特定循环的结果是一个包含 N 个关联数组的索引数组。
  • @Stefan 我对here 所做的唯一更改是从多行字符串而不是多行文件中读取。您必须同意没有实际差异。结果显然是一个 N 维数组(这是有道理的,因为这将允许您处理具有 2 条以上记录的 CSV;我认为这是目标)。
  • 为了更明显,在您自己代码的循环中,您正在访问$array[0]。因此,在您自己的代码中,您知道$array索引,而不是关联的。
  • @StefanDunn 现在知道了吗?我进一步编辑了我的答案,使其更加清晰。
猜你喜欢
  • 2014-05-13
  • 2014-06-20
  • 1970-01-01
  • 2019-07-08
  • 1970-01-01
  • 1970-01-01
  • 2012-12-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多