-1

I've got an old script from someone that I want to remodel but unfortunately I am not that experienced in PHP. What it does is, it reads article information from a CSV file into an array and then basically posts the output into a HTML table, which can then be saved into a PDF file.

One thing I couldn't quite wrap my head around is, the file provides duplicate lines for an article while only some values changed (size, color etc). The article does have the same name but is not repeated twice in the output, the "new" values are just added to the already existing record and I am quite unsure how to do that. Let me give you a simplified example:

CSV Example:

ArtNo,Name,Color,Size

DEF270, Fingal, Stellar, 3XL

DEF270, Fingal, White, 4XL;

So, in a regular loop, the output would be like this

ArtNo Name Color Size
DEF270 Fingal Stellar 3XL
DEF270 Fingal White 4XL

What I would need is this

ArtNo Name Color Size
DEF270 Fingal Stellar, White 3XL, 4XL

Can you guys give me a hint on how to achieve this?

mickmackusa
  • 43,625
  • 12
  • 83
  • 136
Dreshar
  • 39
  • 5
  • 1
    You can either handle that _while_ you are reading the data into an array already - use the article number as _key_ of your array (article number should be a better criterion for uniqueness, than the name), and then accumulate the data in arrays below that; or you will have to implement what is called a _control break_ while you are creating your output table. – CBroe Nov 08 '22 at 13:52
  • I guess you have a two-dimensional array : one being the whole table containing all the rows and each row being itself a key-value array. And what you search for is a groupBy-like function that aggregates some of the columns based on a multi-column key – titouanbou Nov 08 '22 at 14:01
  • Related: [PHP: Merging adjacent values if duplicates found in a multidimensional array](https://stackoverflow.com/a/42930385/2943403) and [Group by a multidimensionnal array in PHP and concatenate results with comma (without creating unnecessary commas)](https://stackoverflow.com/a/73148789/2943403) and [Concatenate values according to the same key value](https://stackoverflow.com/q/59214059/2943403) and [Group subarrays by one column, make comma-separated values from other column within groups](https://stackoverflow.com/q/45965029/2943403) – mickmackusa Nov 08 '22 at 23:43
  • [Group subarray data by one column and form comma-separated values from the secondary value in each group](https://stackoverflow.com/q/48353616/2943403) and [How to store column data as comma separated values when finding duplicate values in another column?](https://stackoverflow.com/q/51247597/2943403) and [Regroup multidimensional array to reverse presentation of many-to-many relationship](https://stackoverflow.com/q/59249492/2943403) – mickmackusa Nov 08 '22 at 23:46
  • [Group rows of a multidimensional array and form comma-separated values within each group](https://stackoverflow.com/q/14255369/2943403) – mickmackusa Nov 08 '22 at 23:53

2 Answers2

2

Let you loaded data from CSV to plain array. After this you can apply array_reduce in next way:

$res = array_reduce(
        $rows,
        function($res, $row) {
            if (isset($res[$row[0]])) {
                $res[$row[0]][1] .= ", $row[1]";
                $res[$row[0]][2] .= ", $row[2]";
                $res[$row[0]][3] .= ", $row[3]";
            }
            else $res[$row[0]] = $row;
            return $res;
        },
        []
    );
var_export($res);

PHPize - run php code online

Slava Rozhnev
  • 9,510
  • 6
  • 23
  • 39
  • This won't work properly when having for example a same color, but different size. `DEF270, Fingal, White, XL`. See https://phpize.online/sql/mysql57/undefined/php/php8/16bf731b9d3eea0e665e7a8e8c0b29e2/ – Markus Zeller Nov 08 '22 at 14:52
  • @Markus that is a good indication that the question needs a fuller [mcve]. – mickmackusa Nov 08 '22 at 23:39
0

You can process the whole file by grouping the article number and add the properties to each an array. On output you implode them comma delimited.

$csv = <<<'_CSV'
ArtNo,Name,Color,Size
DEF270, Fingal, Stellar, 3XL
DEF270, Fingal, White, 4XL;
_CSV;

$csv_handle = fopen('php://memory', 'rw');
$fwrite     = fwrite($csv_handle, $csv);
fseek($csv_handle, 0);

$articles = [];
while (($data = fgetcsv($csv_handle)) !== false) {
    [$articleNumber, $name, $color, $size] = array_map('trim', $data);
    if (!isset($articles[$articleNumber])) {
        $articles[$articleNumber] = [
            'names'  => [$name],
            'colors' => [$color],
            'sizes'  => [$size],
        ];
        continue;
    }
    $article = &$articles[$articleNumber];
    if (!in_array($name, $article['names'])) {
        $article['names'][] = $name;
    }
    if (!in_array($color, $article['colors'])) {
        $article['colors'][] = $color;
    }
    if (!in_array($size, $article['sizes'])) {
        $article['sizes'][] = $size;
    }
    unset ($article);
}
fclose($csv_handle);

echo "<table>\n";
foreach ($articles as $articleNumber => $article) {
    $names  = implode(', ', $article['names']);
    $colors = implode(', ', $article['colors']);
    $sizes  = implode(', ', $article['sizes']);
    echo "<tr><td>$articleNumber</td><td>$names</td><td>$colors</td><td>$sizes</tr>\n";
}
echo "</table>\n";

Output

<table>
<tr><td>ArtNo</td><td>Name</td><td>Color</td><td>Size</tr>
<tr><td>DEF270</td><td>Fingal</td><td>Stellar, White</td><td>3XL, 4XL;</tr>
</table>
Markus Zeller
  • 8,516
  • 2
  • 29
  • 35