如何使用 fputcsv 将多维数组导出到特定的 .csv 布局 PHP

How to export a multi dimensional array to a specific .csv layout with fputcsv PHP

我知道这个问题的答案很明显,但我在过去 3 天里一直在努力找出答案。我无法将 Multi-Dimensional 数组导出到导出的 .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);

这给了我这个布局,但它只显示有一个 child 数组,并没有输出 child 数组的数据。

以上是我得到的输出。

下面是我要实现的布局。

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

总而言之,我想将 $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',
    ),
  ),

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

$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
    ])
  }

}

好的,因为数组格式不正确,代码有点冗长,我想说我们

  • 首先,通过弹出数组中的第一个条目来打印 headers。
  • 通过获取行条目可以与条目值一起使用的最大深度/最大计数,使每行具有相同数量的条目。
  • 打印使用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);

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

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

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

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

代码:(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);

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