This is more of a PHP question than a Kirby one. I have an array of this type:
$products = [
['id' => 'DA-0000'],
['id' => 'DA-0154'],
['id' => 'DA-0154']
];
and I want to create virtual pages from it. Each unique id
should become a parent virtual page, so the above would produce two virtual pages, ‘DA-0000’ and ‘DA-0154’. These pages should contain the children that have the same id
as the parent, for example ‘DA-0000’ would contain a single child (‘DA-0000’), and ‘DA-0154’ should contain two children (two 'DA-0154’s).
Expected result:
Array
(
[DA-0000] => Array
(
[slug] => 'DA-0000'
// more properties
[children] => Array
(
// 'DA-0000' page
)
)
[DA-0154] => Array
(
[slug] => 'DA-0154'
// more properties
[children] => Array
(
// 'DA-0154-1' page
// 'DA-0154-2' page
)
)
)
I can create Kirby virtual pages, but can’t figure out a loop to achieve the above structure.
$products = [
['id' => 'DA-0000'],
['id' => 'DA-0154'],
['id' => 'DA-0154']
];
$ids = array_column($products, 'id');
dump($ids);
$valueCount = array_count_values($ids);
dump($value_count);
$valueCount will give you an array like this.
Array
(
[DA-0000] => 1
[DA-0154] => 2
)
You can then loop through this array and build the structure you need.
I managed to solve it like this: (There was an additional requirement I skipped in my original post to keep it simpler. If the products product
key ends with ‘-0000’ I must use the barcode
key as an id, if not, the ‘product’.)
$db_products = [
['product' => 'DA-0000', 'barcode' => '30970'],
['product' => 'DA-0154', 'barcode' => '48756'],
['product' => 'DA-0154', 'barcode' => '48757']
];
$products = [];
$ids = array_map(function($item) use ($db_products) {
return endsWith($item['product'], '-0000') ? $item['barcode'] : $item['product'];
}, $db_products);
/* $ids:
Array
(
[0] => 30970
[1] => DA-0154
[2] => DA-0154
)*/
$variations_count = array_count_values($ids);
/* $variations_count
Array
(
[30970] => 1
[DA-0154] => 2
)*/
foreach ($variations_count as $id => $variations) {
$children = array_slice($db_products,
array_search($id, array_column($db_products, startsWithNumber($id) ? 'barcode' : 'product')),
$variations);
$products[] = [
'slug' => $id,
'children' => $children
];
}
For each unique id
(product or barcode), I am searching through the db_products
array to find the first key that matches id
, use the variations_count
to determine the length of the search, and build the children array.
I am not sure if this is the best way performance-wise. Would this loop work fast for hundreds of products? Any other suggestions?