php - Group data in csv rows by one column and create comma-separated values from other columns within each group

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

Answer

Solution:

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

Answer

Solution:

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>

Source