无法使用foreach从CSV中提取第一个$ key

时间:2017-12-07 15:42:29

标签: php foreach fgetcsv

我试图将数据从foreach循环中拉出来,但我遇到了一个我还没有遇到的奇怪现象。

CSV的第一行如下所示:

Part Number,Description,List Price

然后数据等等。

我有什么:

ini_set('auto_detect_line_endings', TRUE);
if (($openItems = fopen($uploadFile, 'r')) !== FALSE) {
   foreach (fgetcsv($openItems) as $key => $value) {
        $value = preg_replace('/\h+/', '', strtolower($value));
        echo $value;
        echo ' = ' . $key . " ";
        switch ($value) {
            case "partnumber":
                $pn = $key;
                break;
            case "description":
                $des = $key;
                break;
            case "listprice":
                $lp = $key;
                break;
        }
    }
    print_r("\npn: " . $pn . " des: " . $des . " lp: " . $lp);
}

打印:

partnumber = 0 description = 1 listprice = 2 
pn:  des: 1 lp: 2

正如您所看到的那样,第一列是假的,因此未分配正确的值。

替代打印:

test = 0 partnumber = 1 description = 2 listprice = 3 
pn: 1 des: 2 lp: 3

类型检查:

echo "I'm of Type ". gettype($value) . ". ";

返回:

partnumber = 0 I'm of Type string. description = 1 I'm of Type string. listprice = 2 I'm of Type string. 

旁注:

case "partnumber":
    $pn = $key;
    break;
永远不会访问

case "partnumber":
    $pn = $key;
    echo "I Worked!";
    break;

返回时没有任何结果。

任何建议?

这个场景归功于@azjezz

$csv = [];
ini_set('auto_detect_line_endings', TRUE);
if (($openItems = fopen($uploadFile, 'r')) !== FALSE) {
    foreach (fgetcsv($openItems) as $key => $value) {
        $value = preg_replace('/\h+/', '', strtolower($value));
        $csv[$value] = (Int) $key;
        echo $value;
        echo ' = ' . $key . " ";
        switch ($csv[$value]) {
            case "partnumber":
                $pn = $key;
                break;
            case "description":
                $des = $key;
                break;
            case "listprice":
                $lp = $key;
                break;
        }
    }
    print_r("\npn: " . $pn . " des: " . $des . " lp: " . $lp);
}

结果:

partnumber = 0 description = 1 listprice = 2 
pn: 0 des:  lp: 

另一个奇怪的scinario:

    switch ((int) $value) {
        case "partnumber":
            $pn = $key;
            break;
        case "description":
            $des = $key;
            break;
        case "listprice":
            $lp = $key;
            break;
    }

返回:

partnumber = 0 description = 1 listprice = 2 
pn: 2 des:  lp: 

2 个答案:

答案 0 :(得分:0)

我希望你不介意我为你的追随者提出另一种方法。

ini_set('auto_detect_line_endings', TRUE);
if (($openItems = fopen($uploadFile, 'r')) !== FALSE) {
    // Read the header line with the field names in it
    $keyLine = fgets($openItems);
    $keyLine = preg_replace('/\h+/', '', strtolower($keyLine));
    // Convert the line into an array of field names
    $keys = str_getcsv($keyLine);
    // While you have some more data in the file...
    while ( $data = fgetcsv($openItems)) {
        $csv = [];
        $csv['pn'] = $data[array_search('partnumber', $keys )];
        $csv['lp'] = $data[array_search('listprice', $keys )];
        $csv['des'] = $data[array_search('description', $keys )];
        print_r($csv);
    }
    fclose($openItems);
}

希望这比你努力工作更简单,更简洁。主循环只读取一行,然后检查行中任何特定元素的位置(最好将其分配给存储的值,而不是每次都使用array_search。)

可以改进的一点是它假设每个领域都存在。您可以添加额外的逻辑来说明如果描述字段不存在则不要尝试为其获取值。

答案 1 :(得分:0)

我跑的时候:

var_dump($value);

我得到了:

string(13) "partnumber"
string(11) "description"
string(9) "listprice"

但是partnumber中有10个字符,这意味着隐藏的字符正在通过。所以我将正则表达式改为:

$value = trim(preg_replace('/[^a-z]+/', '', strtolower($value)));