Как экспортировать многомерный массив в определенный макет .csv с помощью fputcsv PHP

Я знаю, что ответ на этот вопрос будет очевиден, но я провел последние 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);

Это дает мне этот макет, но он просто показывает, что есть дочерний массив, и не выводит данные дочерних массивов.

[Image 1]Выше показан результат, который я получаю.

Ниже приведен макет, которого я хочу достичь.

[Изображение 2]

Я также пробовал цикл 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',
    ),
  ),

person Biwwabong    schedule 03.07.2020    source источник
comment
Так игнорировать все пустые?   -  person nice_dev    schedule 03.07.2020
comment
Можете ли вы вместо этого показать var_export() вашего массива?   -  person nice_dev    schedule 03.07.2020
comment
Почему вы не хотите дублировать поле «Заголовок» для каждой строки? Желаемый результат не поддается сортировке или фильтрации каким-либо значимым образом. Кроме того, что случилось с пустыми строками в массиве? Являются ли они заполнителями для строк CSV, которые следует вставить? Можете ли вы изменить массив, чтобы отфильтровать их?   -  person Duroth    schedule 03.07.2020
comment
Пустые можно игнорировать, если макет такой же, как у второго изображения.   -  person Biwwabong    schedule 03.07.2020
comment
Пустые значения являются заполнителями для строк CSV.   -  person Biwwabong    schedule 03.07.2020
comment
@Biwwabong var_export() ?   -  person nice_dev    schedule 03.07.2020
comment
@vivek_23 Я добавил var_export()   -  person Biwwabong    schedule 03.07.2020


Ответы (3)


Хорошо, так как массив искажен, а код немного длинный, я хотел бы сказать, что мы

  • Сначала распечатайте заголовки, вытащив первую запись в массиве.
  • Сделайте так, чтобы в каждой строке было одинаковое количество записей, получив максимальную глубину / максимальное количество, которое запись строки может иметь со значениями записи.
  • Печатайте каждую новую строку, расположенную симметрично, используя 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);
person nice_dev    schedule 03.07.2020

Ваш начальный массив имеет неверный формат, поскольку он не соответствует размерам дочернего массива и индексам. Это правильное решение, но оно очень хрупкое, потому что существует много предположений о структуре массива.

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

}
person gbalduzzi    schedule 03.07.2020

Первая строка каждой группы содержит максимальное количество столбцов, поэтому ее можно использовать для надежного извлечения данных столбца.

Оторвите значения заголовка и URL-адреса при повторении входного массива, чтобы оставшиеся данные в подмассиве имели согласованную и легко управляемую структуру.

Строки с отсутствующими конечными столбцами не имеют значения при отправке строк csv в файл, поэтому создание пустых строк является пустой тратой кода. И наоборот, начальные значения пустых столбцов будут проблемой - вот почему я добавляю две пустые строки, когда не добавляю первую строку соответствующей группы.

Ознакомьтесь со стандартами кодирования PSR, чтобы ознакомиться с рекомендациями по использованию пробелов и фигурных скобок.

Код: (Демо)

$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);

См. демо для вывода в виде массива.

person mickmackusa    schedule 03.07.2020