jarvis Posted March 5, 2019 Share Posted March 5, 2019 Hi All, I hope i'm posting in the right place but also hope someone can help! I've got the following code: <?php $variations = $product->get_available_variations(); if ($variations): ?> <div class="table-responsive"> <table class="table table-striped"> <tbody> <?php foreach ($variations as $key => $value) : ?> <tr> <td><?php echo $value['sku']; ?> <?php echo $value['variation_id']; ?></td> <?php foreach ($value['attributes'] as $attrKey => $attr) : $tax = str_replace('attribute_', '', $attrKey); $term_obj = get_term_by('slug', $attr, $tax); ?> <td><?php echo $term_obj->name; ?></td> <?php endforeach; ?> </tr> <?php endforeach; #$variations?> </tbody> </table> </div><!-- /table-responsive --> <?php endif; #$variations ?> This produces the following table: Product code System Pack Quantity Variation XT1ECWH 234 System 1 2 N/A XT2ECLWH 236 System 2 2 Left XT2ECRWH 237 System 2 2 Right XT3ECWH 238 System 3 2 N/A However, is it possible to alter the code to group the information? So it looks like the below? System 1 System 2 System 3 System 1 XT1ECWH 234 Pack Quantity: 2 Variation: N/A System 2 XT2ECLWH 236 Pack Quantity: 2 Variation: Left XT2ECRWH 237 Pack Quantity: 2 Variation: Right System 3 Sorry, not sure why it's not formatted correctly but hopefully you can see what I'm trying to achieve. The array for $variations is as follows: Array ( [0] => Array ( [attributes] => Array ( [attribute_pa_system] => system-1 [attribute_pa_pack-quantity] => 2 [attribute_pa_variation] => n-a ) [sku] => XT1ECWH [variation_description] => [variation_id] => 234 ) [1] => Array ( [attributes] => Array ( [attribute_pa_system] => system-2 [attribute_pa_pack-quantity] => 2 [attribute_pa_variation] => left ) [sku] => XT2ECLWH [variation_description] => Left [variation_id] => 236 ) [2] => Array ( [attributes] => Array ( [attribute_pa_system] => system-2 [attribute_pa_pack-quantity] => 2 [attribute_pa_variation] => right ) [sku] => XT2ECRWH [variation_description] => Right [variation_id] => 237 ) [3] => Array ( [attributes] => Array ( [attribute_pa_system] => system-3 [attribute_pa_pack-quantity] => 2 [attribute_pa_variation] => n-a ) [price_html] => [sku] => XT3ECWH [variation_description] => ) ) If it helps, I need to always group by the first attribute, in this case : attribute_pa_system Any help on this would be very much appreciated! Thank you in advanced. Quote Link to comment Share on other sites More sharing options...
Barand Posted March 5, 2019 Share Posted March 5, 2019 Try $systems = []; foreach ($variations as $var) { if (!isset($systems[$var['attributes']['attribute_pa_system']])) { $systems[$var['attributes']['attribute_pa_system']] = []; } $systems[$var['attributes']['attribute_pa_system']][] = [ 'sku' => $var['sku'], 'var_id' => $var['variation_id'] ?? '', 'variation' => $var['attributes']['attribute_pa_variation'], 'pack_qty' => $var['attributes']['attribute_pa_pack-quantity'] ]; } Giving Array ( [system-1] => Array ( [0] => Array ( [sku] => XT1ECWH [var_id] => 234 [variation] => n-a [pack_qty] => 2 ) ) [system-2] => Array ( [0] => Array ( [sku] => XT2ECLWH [var_id] => 236 [variation] => left [pack_qty] => 2 ) [1] => Array ( [sku] => XT2ECRWH [var_id] => 237 [variation] => right [pack_qty] => 2 ) ) [system-3] => Array ( [0] => Array ( [sku] => XT3ECWH [var_id] => [variation] => n-a [pack_qty] => 2 ) ) ) Quote Link to comment Share on other sites More sharing options...
jarvis Posted March 5, 2019 Author Share Posted March 5, 2019 Hi @Barand Thank you for your reply (as always!). May I ask, what does the double question mark mean ('var_id' => $var['variation_id'] ?? '',) Also, as the name is unknown from product to product, rather than a name like $systems[$var['attributes']['attribute_pa_system']] is it possible use a number like: $systems[$var['attributes'][0]] Thanks again Quote Link to comment Share on other sites More sharing options...
Barand Posted March 5, 2019 Share Posted March 5, 2019 How are you creating the $variations array in the first place? "??" is PHP's null coalesce operator $id = $var['variation_id'] ?? ''; // equivalent to $id = isset($var['variation_id']) ? $var['variation_id'] : ''; it returns the first non-null value $a = null; $b = null; $c = 100; $d = 200; echo $a ?? $b ?? $c ?? $d; //--> 100 Quote Link to comment Share on other sites More sharing options...
jarvis Posted March 5, 2019 Author Share Posted March 5, 2019 Thanks @Barand The variations (attributes) are created within a CMS. So there are various ones: System Pack Quantity Variation Colour Then each attribute has related terms, for example: System - System 1, System 2 etc. Pack Quantity - 1,2,3,10 etc. Variation: Left, Right Colour - Black, White, Grey When a product's created, you specify which Attributes you want and select the necessary variations So $variations then contains the necessary product variations As products differ with which option is first, it'd be ideal not to use a name you see, hence wondering whether you can use the [0] to denote the first attribute instead - I hope that makes sense!? Quote Link to comment Share on other sites More sharing options...
Barand Posted March 5, 2019 Share Posted March 5, 2019 revised $systems = []; foreach ($variations as $var) { $var['attributes'] = array_values($var['attributes']); // ADD THIS LINE TO CONVERT TO NUMERIC INDEX if (!isset($systems[$var['attributes'][0]])) { $systems[$var['attributes'][0]] = []; } $systems[$var['attributes'][0]][] = [ 'sku' => $var['sku'], 'var_id' => $var['variation_id'] ?? '', 'variation' => $var['attributes'][2], 'pack_qty' => $var['attributes'][1] ]; } Quote Link to comment Share on other sites More sharing options...
jarvis Posted March 5, 2019 Author Share Posted March 5, 2019 Thank you so much! I get a notice of Notice: Undefined offset: 2 which relates to this line: 'variation' => $var['attributes'][2], so now trying to work out what may be causing this Thank you again for all your help Quote Link to comment Share on other sites More sharing options...
jarvis Posted March 5, 2019 Author Share Posted March 5, 2019 Ah it's because not every product has that specific attribute Is there a way to add a conditional check within the array? Quote Link to comment Share on other sites More sharing options...
jarvis Posted March 5, 2019 Author Share Posted March 5, 2019 HI @Barand Sorry to trouble you further. If you have the array coming in with: ( [sku] => XT1ECWH [var_id] => 234 [variation] => n-a [pack_qty] => 2 ) Within your code, you currently have: $systems[$var['attributes'][0]][] = [ 'sku' => $var['sku'], 'var_id' => $var['variation_id'] ?? '', 'pack_qty' => $var['attributes'][1], 'variation' => $var['attributes'][2] ]; Which is utterly brill, however, from product to product, the attributes may differ (some have more, some have less, some are different). For example: ( [sku] => XT1ECWH [var_id] => 234 [variation] => n-a [colour] => black [pack_qty] => 2 [material] => plastic ) Is there anyway to dynamically create the internal part? $systems[$var['attributes'][0]][] = [ 'sku' => $var['sku'], 'var_id' => $var['variation_id'] ?? '', //some sort of loop here to gather the below? // 'pack_qty' => $var['attributes'][1], 'variation' => $var['attributes'][2] ]; Is that even possible? Quote Link to comment Share on other sites More sharing options...
Barand Posted March 5, 2019 Share Posted March 5, 2019 You could do something like this, but you will have a problem with your final output's headings if you don't know in advance what your inputs are going to be. $systems = []; foreach ($variations as $var) { $atts = array_values($var['attributes']); $key = $atts[0]; $kv = count($var); $ka = count($var['attributes']); if (!isset($systems[$key])) { $systems[$key] = []; } $systems[$key][] = array_merge(array_slice($var['attributes'], 1, $ka-1, 1), array_slice($var, 1, $kv-1, 1)); } echo '<pre>', print_r($systems, 1), '</pre>'; Quote Link to comment Share on other sites More sharing options...
jarvis Posted March 5, 2019 Author Share Posted March 5, 2019 Thanks @Barand Hmm, I hadn't given that a thought! If i'm honest, i'm struggling a little as to how to output this anyway I hate arrays or they hate me, haven't decided which Quote Link to comment Share on other sites More sharing options...
Barand Posted March 5, 2019 Share Posted March 5, 2019 The easy solution would be to use the array keys as the headings but they would need to be a little more user-friendly than 'attribute_pa_pack-quantity'. Alternatively you need to map each attribute name to an output heading ( EG 'attribute_pa_pack-quantity' => 'Pack Quantity') Quote Link to comment Share on other sites More sharing options...
jarvis Posted March 5, 2019 Author Share Posted March 5, 2019 (edited) Thanks @Barand I could do that, then use str replace to tidy it up - not ideal but a workable solution, what do you think? As I say, I could do with a pointer as to how to display the table though if possible? Sorry for asking! As a thought, the heading would always be the first attribute, so in theory would be 'attribute_pa_system' Edited March 5, 2019 by jarvis Updated info on first attribute for headers Quote Link to comment Share on other sites More sharing options...
Barand Posted March 5, 2019 Share Posted March 5, 2019 This should get you on your way <?php $systems = []; foreach ($variations as $var) { $atts = array_values($var['attributes']); $key = $atts[0]; $kv = count($var); $ka = count($var['attributes']); if (!isset($systems[$key])) { $systems[$key] = []; } $systems[$key][] = array_merge(array_slice($var['attributes'], 1, $ka-1, 1), array_slice($var, 1, $kv-1, 1)); } ?> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>Example</title> <style type='text/css'> body { font-family: calibri, sans-serif; font-size: 10pt; } .system { width: 25%; float: left; margin-right: 30px; } .item { padding: 5px; margin-bottom: 15px; } .hdg { display: inline-block; width: 80px; font-weight: 600; } </style> </head> <body> <?php foreach ($systems as $sys => $sdata) { echo "<div class='system'><h3>$sys</h3>\n"; foreach ($sdata as $item) { echo "<div class='item'>\n"; foreach ($item as $h => $v) { if ($v) { echo "<div class='hdg'>{$headings[$h]}</div>$v<br>\n"; } } echo "</div>\n"; } echo "</div>\n"; } ?> which gives Quote Link to comment Share on other sites More sharing options...
jarvis Posted March 5, 2019 Author Share Posted March 5, 2019 Thank you so much @Barand for all of your help! Quote Link to comment Share on other sites More sharing options...
jarvis Posted March 5, 2019 Author Share Posted March 5, 2019 What would cause: Notice: Array to string conversion in... line 93 This refers to echo "<div class='hdg'>{$headings[$h]}</div>$v<br>\n"; Quote Link to comment Share on other sites More sharing options...
Barand Posted March 5, 2019 Share Posted March 5, 2019 It seems to have $headings[$h] as an array. What does your $headings array look like? Quote Link to comment Share on other sites More sharing options...
Barand Posted March 5, 2019 Share Posted March 5, 2019 Looks like I missed mine from my code $headings = [ 'attribute_pa_pack-quantity' => 'Pack Qty', 'attribute_pa_variation' => 'Variation', 'sku' => 'SKU', 'variation_description' => 'Var Desc', 'variation_id' => 'Id', 'price_html' => 'Price' ]; Quote Link to comment Share on other sites More sharing options...
jarvis Posted March 5, 2019 Author Share Posted March 5, 2019 Hi @Barand Mine looks like this: Array ( [attribute_pa_pack-quantity] => [dimensions] => [dimensions_html] => [image] => [image_id] => [is_in_stock] => [is_purchasable] => [is_sold_individually] => [min_qty] => [sku] => [variation_id] => [variation_is_active] => [variation_is_visible] => [weight_html] => ) I did remove a couple of items from the outset to tidy the initial array output (very first post). I'm sorry, I thought it would make life easier but wonder if I've now muddled the situation in doing so!? Otherwise it was rather lengthy: Array ( [0] => Array ( [attributes] => Array ( [attribute_pa_system] => system-1 [attribute_pa_pack-quantity] => 1-x-3m ) [availability_html] => [backorders_allowed] => [dimensions] => Array ( [length] => [width] => [height] => ) [dimensions_html] => N/A [display_price] => 0 [display_regular_price] => 0 [image] => Array ( [title] => xt1cwh_web_600 [caption] => [url] => https://www.domain.co.uk/wp-content/uploads/2019/01/xt1cwh_web_600.png [alt] => [src] => https://www.domain.co.uk/wp-content/uploads/2019/01/xt1cwh_web_600-600x600.png [srcset] => https://www.domain.co.uk/wp-content/uploads/2019/01/xt1cwh_web_600.png 600w, https://www.domain.co.uk/wp-content/uploads/2019/01/xt1cwh_web_600-400x400.png 400w, https://www.domain.co.uk/wp-content/uploads/2019/01/xt1cwh_web_600-150x150.png 150w, https://www.domain.co.uk/wp-content/uploads/2019/01/xt1cwh_web_600-250x250.png 250w, https://www.domain.co.uk/wp-content/uploads/2019/01/xt1cwh_web_600-120x120.png 120w, https://www.domain.co.uk/wp-content/uploads/2019/01/xt1cwh_web_600-100x100.png 100w [sizes] => (max-width: 600px) 100vw, 600px [full_src] => https://www.domain.co.uk/wp-content/uploads/2019/01/xt1cwh_web_600.png [full_src_w] => 600 [full_src_h] => 600 [gallery_thumbnail_src] => https://www.domain.co.uk/wp-content/uploads/2019/01/xt1cwh_web_600-100x100.png [gallery_thumbnail_src_w] => 100 [gallery_thumbnail_src_h] => 100 [thumb_src] => https://www.domain.co.uk/wp-content/uploads/2019/01/xt1cwh_web_600-400x400.png [thumb_src_w] => 400 [thumb_src_h] => 400 [src_w] => 600 [src_h] => 600 ) [image_id] => 719 [is_downloadable] => [is_in_stock] => 1 [is_purchasable] => 1 [is_sold_individually] => no [is_virtual] => [max_qty] => [min_qty] => 1 [price_html] => [sku] => XT1CWH [variation_description] => [variation_id] => 199 [variation_is_active] => 1 [variation_is_visible] => 1 [weight] => [weight_html] => N/A ) [1] => Array ( [attributes] => Array ( [attribute_pa_system] => system-2 [attribute_pa_pack-quantity] => 1-x-3m ) [availability_html] => [backorders_allowed] => [dimensions] => Array ( [length] => [width] => [height] => ) [dimensions_html] => N/A [display_price] => 0 [display_regular_price] => 0 [image] => Array ( [title] => xt1cwh_web_600 [caption] => [url] => https://www.domain.co.uk/wp-content/uploads/2019/01/xt1cwh_web_600.png [alt] => [src] => https://www.domain.co.uk/wp-content/uploads/2019/01/xt1cwh_web_600-600x600.png [srcset] => https://www.domain.co.uk/wp-content/uploads/2019/01/xt1cwh_web_600.png 600w, https://www.domain.co.uk/wp-content/uploads/2019/01/xt1cwh_web_600-400x400.png 400w, https://www.domain.co.uk/wp-content/uploads/2019/01/xt1cwh_web_600-150x150.png 150w, https://www.domain.co.uk/wp-content/uploads/2019/01/xt1cwh_web_600-250x250.png 250w, https://www.domain.co.uk/wp-content/uploads/2019/01/xt1cwh_web_600-120x120.png 120w, https://www.domain.co.uk/wp-content/uploads/2019/01/xt1cwh_web_600-100x100.png 100w [sizes] => (max-width: 600px) 100vw, 600px [full_src] => https://www.domain.co.uk/wp-content/uploads/2019/01/xt1cwh_web_600.png [full_src_w] => 600 [full_src_h] => 600 [gallery_thumbnail_src] => https://www.domain.co.uk/wp-content/uploads/2019/01/xt1cwh_web_600-100x100.png [gallery_thumbnail_src_w] => 100 [gallery_thumbnail_src_h] => 100 [thumb_src] => https://www.domain.co.uk/wp-content/uploads/2019/01/xt1cwh_web_600-400x400.png [thumb_src_w] => 400 [thumb_src_h] => 400 [src_w] => 600 [src_h] => 600 ) [image_id] => 719 [is_downloadable] => [is_in_stock] => 1 [is_purchasable] => 1 [is_sold_individually] => no [is_virtual] => [max_qty] => [min_qty] => 1 [price_html] => [sku] => XT2CWH [variation_description] => [variation_id] => 200 [variation_is_active] => 1 [variation_is_visible] => 1 [weight] => [weight_html] => N/A ) [2] => Array ( [attributes] => Array ( [attribute_pa_system] => system-3 [attribute_pa_pack-quantity] => 1-x-3m ) [availability_html] => [backorders_allowed] => [dimensions] => Array ( [length] => [width] => [height] => ) [dimensions_html] => N/A [display_price] => 0 [display_regular_price] => 0 [image] => Array ( [title] => xt1cwh_web_600 [caption] => [url] => https://www.domain.co.uk/wp-content/uploads/2019/01/xt1cwh_web_600.png [alt] => [src] => https://www.domain.co.uk/wp-content/uploads/2019/01/xt1cwh_web_600-600x600.png [srcset] => https://www.domain.co.uk/wp-content/uploads/2019/01/xt1cwh_web_600.png 600w, https://www.domain.co.uk/wp-content/uploads/2019/01/xt1cwh_web_600-400x400.png 400w, https://www.domain.co.uk/wp-content/uploads/2019/01/xt1cwh_web_600-150x150.png 150w, https://www.domain.co.uk/wp-content/uploads/2019/01/xt1cwh_web_600-250x250.png 250w, https://www.domain.co.uk/wp-content/uploads/2019/01/xt1cwh_web_600-120x120.png 120w, https://www.domain.co.uk/wp-content/uploads/2019/01/xt1cwh_web_600-100x100.png 100w [sizes] => (max-width: 600px) 100vw, 600px [full_src] => https://www.domain.co.uk/wp-content/uploads/2019/01/xt1cwh_web_600.png [full_src_w] => 600 [full_src_h] => 600 [gallery_thumbnail_src] => https://www.domain.co.uk/wp-content/uploads/2019/01/xt1cwh_web_600-100x100.png [gallery_thumbnail_src_w] => 100 [gallery_thumbnail_src_h] => 100 [thumb_src] => https://www.domain.co.uk/wp-content/uploads/2019/01/xt1cwh_web_600-400x400.png [thumb_src_w] => 400 [thumb_src_h] => 400 [src_w] => 600 [src_h] => 600 ) [image_id] => 719 [is_downloadable] => [is_in_stock] => 1 [is_purchasable] => 1 [is_sold_individually] => no [is_virtual] => [max_qty] => [min_qty] => 1 [price_html] => [sku] => XT3CWH [variation_description] => [variation_id] => 201 [variation_is_active] => 1 [variation_is_visible] => 1 [weight] => [weight_html] => N/A ) ) Apologies if this completely screws things!? Quote Link to comment Share on other sites More sharing options...
Barand Posted March 5, 2019 Share Posted March 5, 2019 9 minutes ago, jarvis said: Apologies if this completely screws things!? No need to apologise. You are the one who is going to be adapting the sample code I gave you so it does what you really want to do. Quote Link to comment Share on other sites More sharing options...
Barand Posted March 5, 2019 Share Posted March 5, 2019 Attribute which are arrays (like "image" are ignored, as are attributes with no values. Where no heading translation is provided the raw attribute name is output. <?php $headings = [ 'attribute_pa_pack-quantity' => 'Pack Qty', 'attribute_pa_variation' => 'Variation', 'sku' => 'SKU', 'variation_description' => 'Var Desc', 'variation_id' => 'Id', 'price_html' => 'Price' ]; $systems = []; foreach ($variations as $var) { $atts = array_values($var['attributes']); $key = $atts[0]; $kv = count($var); $ka = count($var['attributes']); if (!isset($systems[$key])) { $systems[$key] = []; } $systems[$key][] = array_merge(array_slice($var['attributes'], 1, $ka-1, 1), array_slice($var, 1, $kv-1, 1)); } echo '<pre>', print_r($systems, 1), '</pre>'; ?> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>Example</title> <style type='text/css'> body { font-family: calibri, sans-serif; font-size: 10pt; } .system { width: 30%; float: left; margin-right: 30px; } .item { padding: 5px; margin-bottom: 15px; } .hdg { display: inline-block; width: 150px; font-weight: 600; } </style> </head> <body> <?php foreach ($systems as $sys => $sdata) { echo "<div class='system'><h3>$sys</h3>\n"; foreach ($sdata as $item) { echo "<div class='item'>\n"; foreach ($item as $h => $v) { if ($v && !is_array($v)) { $hd = $headings[$h] ?? $h; // use attribute key if no translation available echo "<div class='hdg'>{$hd}</div>$v<br>\n"; } } echo "</div>\n"; } echo "</div>\n"; } ?> </body> </html> 1 Quote Link to comment Share on other sites More sharing options...
jarvis Posted March 6, 2019 Author Share Posted March 6, 2019 Hi @Barand Sorry for the delay replying. Thank you so, so much! That's absolutely bloody brilliant I think I can work out how to remove the bits and bobs I don't need to display (image_id, is_in_stock etc.) Thank you once again! Quote Link to comment Share on other sites More sharing options...
Barand Posted March 6, 2019 Share Posted March 6, 2019 One way would be to use the $headings array. Provide a translation for all those you want to include and ignore those that are not in the array. You could also think about extending that array to provide the sequence for attribute output, Quote Link to comment Share on other sites More sharing options...
jarvis Posted March 6, 2019 Author Share Posted March 6, 2019 Well that sounds jolly interesting and not something i've done before. I'll go and look into it Thanks again Quote Link to comment Share on other sites More sharing options...
jarvis Posted March 7, 2019 Author Share Posted March 7, 2019 HI @Barand Is it possible to ask one more thing? In your very kind example, you have: $headings = [ 'attribute_pa_colour' => 'Colour', 'attribute_pa_description' => 'Description', 'attribute_pa_material' => 'Material', 'attribute_pa_pack-quantity' => 'Pack Quantity', 'attribute_pa_size' => 'Size', 'attribute_pa_system' => 'System', 'attribute_pa_variation' => 'Variation', 'variation_description' => 'Description', 'sku' => 'SKU', 'variation_id' => 'ID', 'price_html' => 'Price' ]; echo '<pre>', print_r($headings), '</pre>'; And if you print his out, you would see: Array ( [attribute_pa_colour] => Colour [attribute_pa_description] => Description [attribute_pa_material] => Material [attribute_pa_pack-quantity] => Pack Quantity [attribute_pa_size] => Size [attribute_pa_system] => System [attribute_pa_variation] => Variation [variation_description] => Description [sku] => SKU [variation_id] => ID [price_html] => Price ) I thought I'd try and automate this, so have the following code: $attribute_taxonomies = wc_get_attribute_taxonomies(); if ( $attribute_taxonomies ) : $taxonomyOfInterest = array(); foreach ($attribute_taxonomies as $tax=>$tax_value) : $attribute = 'attribute_pa_'.$tax_value->attribute_name; $name = 'pa_'.$tax_value->attribute_name; $label = wc_attribute_label( $name ); $taxonomyOfInterest[] = $attribute.' => '.$label.','; endforeach; endif; array_push($taxonomyOfInterest,"'variation_description' => 'Description',", "'sku' => 'SKU',", "'variation_id' => 'ID',", "'price_html' => 'Price'"); echo '<pre>', print_r($taxonomyOfInterest), '</pre>'; But when I print this out, I get: Array ( [0] => attribute_pa_colour => Colour, [1] => attribute_pa_description => Description, [2] => attribute_pa_material => Material, [3] => attribute_pa_pack-quantity => Pack Quantity, [4] => attribute_pa_size => Size, [5] => attribute_pa_system => System, [6] => attribute_pa_variation => Variation, [7] => 'variation_description' => 'Description', [8] => 'sku' => 'SKU', [9] => 'variation_id' => 'ID', [10] => 'price_html' => 'Price' ) Apologies for the terminology but how do I output this as you have it I guess without an index but arrays always need an index, right? Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.