【问题标题】:How to export a multi dimensional array to a specific .csv layout with fputcsv PHP如何使用 fputcsv PHP 将多维数组导出到特定的 .csv 布局
【发布时间】:2020-10-24 03:38:29
【问题描述】:

我知道这个问题的答案是显而易见的,但我在过去 3 天里一直在试图弄清楚。我无法将多维数组导出到导出的 .csv 文件中的正确布局中。

我似乎能够获得所有数据但布局不正确,或者我可以获得正确布局但不是所有数据。

这是数组

array (size=106)
  0 => 
    array (size=6)
      0 => string 'Title' (length=5)
      1 => string 'image_url' (length=9)
      3 => string 'SKU CODE' (length=8)
      4 => string 'TITLE SIZE' (length=10)
      5 => string 'DESCRIPTION' (length=11)
      6 => string 'BASE SKU' (length=8)
  1 => 
    array (size=6)
      0 => string 'A witch and her cat live here' (length=29)
      1 => string 'https://beautifulhomegifts.com/a-witch-and-her-cat-live-here/' (length=61)
      3 => 
        array (size=4)
          0 => string 'BHG-MS-AWAHCLH030720' (length=20)
          1 => string 'BHG-MS-AWAHCLH030720-A5' (length=23)
          2 => string 'BHG-MS-AWAHCLH030720-A4' (length=23)
          3 => string 'BHG-MS-AWAHCLH030720-A3' (length=23)
      4 => 
        array (size=4)
          0 => string 'A witch and her cat live here' (length=29)
          1 => string 'A witch and her cat live here - 150mm x 200mm' (length=45)
          2 => string 'A witch and her cat live here - 201mm x 305mm' (length=45)
          3 => string 'A witch and her cat live here - 305mm x 400mm' (length=45)
      5 => 
        array (size=4)
          0 => string 'A witch and her cat live here' (length=29)
          1 => string 'A witch and her cat live here' (length=29)
          2 => string 'A witch and her cat live here' (length=29)
          3 => string 'A witch and her cat live here' (length=29)
      6 => 
        array (size=3)
          1 => string 'BHG-MS-AWAHCLH030720' (length=20)
          2 => string 'BHG-MS-AWAHCLH030720' (length=20)
          3 => string 'BHG-MS-AWAHCLH030720' (length=20)
  2 => 
    array (size=2)
      0 => string '' (length=0)
      1 => string '' (length=0)
  3 => 
    array (size=2)
      0 => string '' (length=0)
      1 => string '' (length=0)
  4 => 
    array (size=2)
      0 => string '' (length=0)
      1 => string '' (length=0)
  5 => 
    array (size=6)
      0 => string 'Autism House Rules' (length=18)
      1 => string 'https://beautifulhomegifts.com/autism-house-rules/' (length=50)
      3 => 
        array (size=4)
          0 => string 'BHG-MS-AHR030720' (length=16)
          1 => string 'BHG-MS-AHR030720-A5' (length=19)
          2 => string 'BHG-MS-AHR030720-A4' (length=19)
          3 => string 'BHG-MS-AHR030720-A3' (length=19)
      4 => 
        array (size=4)
          0 => string 'Autism House Rules' (length=18)
          1 => string 'Autism House Rules - 150mm x 200mm' (length=34)
          2 => string 'Autism House Rules - 201mm x 305mm' (length=34)
          3 => string 'Autism House Rules - 305mm x 400mm' (length=34)
      5 => 
        array (size=4)
          0 => string 'Autism House Rules' (length=18)
          1 => string 'Autism House Rules' (length=18)
          2 => string 'Autism House Rules' (length=18)
          3 => string 'Autism House Rules' (length=18)
      6 => 
        array (size=3)
          1 => string 'BHG-MS-AHR030720' (length=16)
          2 => string 'BHG-MS-AHR030720' (length=16)
          3 => string 'BHG-MS-AHR030720' (length=16)
  6 => 
    array (size=2)
      0 => string '' (length=0)
      1 => string '' (length=0)
  7 => 
    array (size=2)
      0 => string '' (length=0)
      1 => string '' (length=0)
  8 => 
    array (size=2)
      0 => string '' (length=0)
      1 => string '' (length=0)
  9 => 

我已经尝试了多种方法来让它工作,这是我最接近正确的方法

$f = fopen('new.csv', 'a'); // Configure fOpen to create, open and write only.

if ($f != false){

// Loop over the array and passing in the values only. 
foreach ($the_big_array as $row){
    
 
        fputcsv($f, $row);
    
}
}

fclose($f);

这给了我这个布局,但它只是显示有一个子数组并且不输出子数组的数据。

Above 是我得到的输出。

下面是我想要实现的布局。

我还在 foreach 循环中尝试了一个 foreach 循环来获取数据,当我这样做时,我得到了所有数据,但不是在同一个布局中。我浏览了这里的所有帖子,很多帖子都接近我想要实现的目标,但没有一个给出正确的布局。

总而言之,我想将 $the_big_array 导出到一个 .csv 文件,该文件具有电子表格中 .csv 的第二个图像的布局。谢谢

array (
  0 => 
  array (
    0 => 'Title',
    1 => 'image_url',
    3 => 'SKU CODE',
    4 => 'TITLE SIZE',
    5 => 'DESCRIPTION',
    6 => 'BASE SKU',
  ),
  1 => 
  array (
    0 => 'A witch and her cat live here',
    1 => 'https://beautifulhomegifts.com/a-witch-and-her-cat-live-here/',
    3 => 
    array (
      0 => 'BHG-MS-AWAHCLH030720',
      1 => 'BHG-MS-AWAHCLH030720-A5',
      2 => 'BHG-MS-AWAHCLH030720-A4',
      3 => 'BHG-MS-AWAHCLH030720-A3',
    ),
    4 => 
    array (
      0 => 'A witch and her cat live here',
      1 => 'A witch and her cat live here - 150mm x 200mm',
      2 => 'A witch and her cat live here - 201mm x 305mm',
      3 => 'A witch and her cat live here - 305mm x 400mm',
    ),
    5 => 
    array (
      0 => 'A witch and her cat live here',
      1 => 'A witch and her cat live here',
      2 => 'A witch and her cat live here',
      3 => 'A witch and her cat live here',
    ),
    6 => 
    array (
      1 => 'BHG-MS-AWAHCLH030720',
      2 => 'BHG-MS-AWAHCLH030720',
      3 => 'BHG-MS-AWAHCLH030720',
    ),
  ),
  2 => 
  array (
    0 => '',
    1 => '',
  ),
  3 => 
  array (
    0 => '',
    1 => '',
  ),
  4 => 
  array (
    0 => '',
    1 => '',
  ),
  5 => 
  array (
    0 => 'Autism House Rules',
    1 => 'https://beautifulhomegifts.com/autism-house-rules/',
    3 => 
    array (
      0 => 'BHG-MS-AHR030720',
      1 => 'BHG-MS-AHR030720-A5',
      2 => 'BHG-MS-AHR030720-A4',
      3 => 'BHG-MS-AHR030720-A3',
    ),
    4 => 
    array (
      0 => 'Autism House Rules',
      1 => 'Autism House Rules - 150mm x 200mm',
      2 => 'Autism House Rules - 201mm x 305mm',
      3 => 'Autism House Rules - 305mm x 400mm',
    ),
    5 => 
    array (
      0 => 'Autism House Rules',
      1 => 'Autism House Rules',
      2 => 'Autism House Rules',
      3 => 'Autism House Rules',
    ),
    6 => 
    array (
      1 => 'BHG-MS-AHR030720',
      2 => 'BHG-MS-AHR030720',
      3 => 'BHG-MS-AHR030720',
    ),
  ),

【问题讨论】:

  • 所以忽略所有空的?
  • 你可以显示你的数组的var_export() 吗?
  • 为什么不想为每一行复制标题字段?您想要的输出不能以任何有意义的方式排序或过滤。另外,数组中的空行是怎么回事?它们是应该插入的 CSV 行的占位符吗?你能改变数组来过滤掉它们吗?
  • 空的可以忽略,只要布局和第二张图一样
  • 空值是 CSV 行的占位符

标签: php arrays csv multidimensional-array fputcsv


【解决方案1】:

好的,由于数组格式错误,代码有点长,我想说我们

  • 首先,通过弹出数组中的第一个条目来打印标题。
  • 通过获取行条目可以与条目值一起使用的最大深度/最大计数,使每行具有相同数量的条目。
  • 使用array_column() 打印对称排列的每个新行。您可以在代码中打印$final_row_data 以更好地了解它是如何对称排列的。

片段:

<?php

$the_big_array = array (
    0 =>
    array (
        0 => 'Title',
        1 => 'image_url',
        3 => 'SKU CODE',
        4 => 'TITLE SIZE',
        5 => 'DESCRIPTION',
        6 => 'BASE SKU',
    ),
    1 =>
    array (
        0 => 'A witch and her cat live here',
        1 => 'https://beautifulhomegifts.com/a-witch-and-her-cat-live-here/',
        3 =>
        array (
            0 => 'BHG-MS-AWAHCLH030720',
            1 => 'BHG-MS-AWAHCLH030720-A5',
            2 => 'BHG-MS-AWAHCLH030720-A4',
            3 => 'BHG-MS-AWAHCLH030720-A3',
        ),
        4 =>
        array (
            0 => 'A witch and her cat live here',
            1 => 'A witch and her cat live here - 150mm x 200mm',
            2 => 'A witch and her cat live here - 201mm x 305mm',
            3 => 'A witch and her cat live here - 305mm x 400mm',
        ),
        5 =>
        array (
            0 => 'A witch and her cat live here',
            1 => 'A witch and her cat live here',
            2 => 'A witch and her cat live here',
            3 => 'A witch and her cat live here',
        ),
        6 =>
        array (
            1 => 'BHG-MS-AWAHCLH030720',
            2 => 'BHG-MS-AWAHCLH030720',
            3 => 'BHG-MS-AWAHCLH030720',
        ),
    ),
    2 =>
    array (
        0 => '',
        1 => '',
    ),
    3 =>
    array (
        0 => '',
        1 => '',
    ),
    4 =>
    array (
        0 => '',
        1 => '',
    ),
    5 =>
    array (
        0 => 'Autism House Rules',
        1 => 'https://beautifulhomegifts.com/autism-house-rules/',
        3 =>
        array (
            0 => 'BHG-MS-AHR030720',
            1 => 'BHG-MS-AHR030720-A5',
            2 => 'BHG-MS-AHR030720-A4',
            3 => 'BHG-MS-AHR030720-A3',
        ),
        4 =>
        array (
            0 => 'Autism House Rules',
            1 => 'Autism House Rules - 150mm x 200mm',
            2 => 'Autism House Rules - 201mm x 305mm',
            3 => 'Autism House Rules - 305mm x 400mm',
        ),
        5 =>
        array (
            0 => 'Autism House Rules',
            1 => 'Autism House Rules',
            2 => 'Autism House Rules',
            3 => 'Autism House Rules',
        ),
        6 =>
        array (
            1 => 'BHG-MS-AHR030720',
            2 => 'BHG-MS-AHR030720',
            3 => 'BHG-MS-AHR030720',
        ),
    )
);

$headers = array_shift($the_big_array);
$header_keys = array_keys($headers);

$fhandle = fopen("sample.csv","a+");// have w+ if you want to override each time.

fputcsv($fhandle,$headers);// add headers first

foreach($the_big_array as $row_data){
   $insert_row = [];
   
   // making consistent with all header keys
   foreach($header_keys as $key){
       if(isset($row_data[$key])){
           $insert_row[$key] = $row_data[$key];
       }else{
           $insert_row[$key] = '';
       }       
   }   
   
   if(count(array_filter($insert_row)) == 0) continue;
   
   $final_row_data = [];
   $max_depth_size = 0;
   foreach($insert_row as $value){
       if(is_array($value)){
           $max_depth_size = max($max_depth_size,count($value));
       }
   }
   
   foreach($insert_row as $key => $value){
       $temp = [];
       if(is_array($value)){
           $value = array_values($value); // since data is malformed(would work even if it is ok)
           $val_size = count($value);           
           for($i = 0; $i < $max_depth_size; ++$i){
               if($i >= $val_size) $temp[$i] = '';
               else $temp[$i] = $value[$i];
           }
       }else{
           $temp = array_merge(array($value),array_fill(0, $max_depth_size - 1, ''));
       }
       
       $final_row_data[] = $temp;
   }
   
   for($column = 0;$column < $max_depth_size; ++$column){
       fputcsv($fhandle,array_column($final_row_data, $column)); // add all formatted data to CSV
   }
}

fclose($fhandle);

【讨论】:

    【解决方案2】:

    您的起始数组格式错误,因为它在子数组的维度和索引中不一致。这是一个有效的解决方案,但它非常脆弱,因为对数组结构有很多假设。

    $f = fopen('new.csv', 'a');
    
    // Write the header
    fputcsv($f, array_values(array_shift($the_big_array)));
    
    foreach($the_big_array as $baseRow) {
      if (empty($baseRow[0]) continue
      
      $subRowsCount = count($baseRow[3])
    
      if (
        count($baseRow[4]) !== $subRowsCount 
        || count($baseRow[5]) !== $subRowsCount 
        || count($baseRow[6]) !== $subRowsCount - 1)
      } {
        // Check that the sub-arrays dimensions are consistent or ignore the row
        continue;
      }
    
      for($i = 0; $i < $subRowsCount; $i++) {
        fputcsv($f, [
          $i === 0 ? $baseRow[0] : '', // Title
          $i === 0 ? $baseRow[1] : '', // image_url
          $baseRow[3][$i],  // SKU code
          $baseRow[4][$i],  // Title size
          $baseRow[5][$i],  // Description
          $i === 0 ? '' : $baseRow[6][$i-1] // Base sku
        ])
      }
    
    }
    

    【讨论】:

      【解决方案3】:

      每个“组”的第一行包含最大列数,因此可用于可靠地获取列数据。

      在迭代输入数组时撕下 title 和 url 值,以便子数组中的剩余数据具有一致且易于操作的结构。

      在将 csv 行推送到文件中时,缺少尾随列的行无关紧要,因此费心生成空字符串是一种代码浪费。相反,前导空列值将是一个问题——这就是为什么我在不添加相应组的第一行时添加两个空字符串的原因。

      阅读 PSR 编码标准,了解有关间距和花括号用法的建议。

      代码:(Demo)

      $headers = array_shift($array);
      
      $fhandle = fopen("new.csv", "a");
      
      fputcsv($fhandle, $headers);
      
      foreach ($array as $row) {
          if (empty($row[0])) {
              continue;
          }
      
          $titleAndUrl = array_splice($row, 0, 2);
         
          foreach ($row[0] as $column => $notUsed) {
              fputcsv(
                  $fhandle,
                  array_merge(
                      !$column ? $titleAndUrl : ['', ''],
                      array_column($row, $column)
                  )
              );
          }
      }
      
      fclose($fhandle);
      

      查看演示以获取数组形式的输出。

      【讨论】: