Jump to content

PHP Group Array


jarvis

Recommended Posts

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.

Link to comment
Share on other sites

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
                )

        )

)

 

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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

 

Link to comment
Share on other sites

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!?

Link to comment
Share on other sites

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]
                                        ];
}

 

Link to comment
Share on other sites

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 

 

Link to comment
Share on other sites

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?

Link to comment
Share on other sites

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>';

 

Link to comment
Share on other sites

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')

Link to comment
Share on other sites

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' 

Link to comment
Share on other sites

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

Capture.PNG

Link to comment
Share on other sites

Looks like I missed mine from my code

$headings = [ 'attribute_pa_pack-quantity' => 'Pack&nbsp;Qty',
              'attribute_pa_variation' => 'Variation',
              'sku' => 'SKU',
              'variation_description' => 'Var&nbsp;Desc',
              'variation_id' => 'Id',
              'price_html' => 'Price'
            ];

 

Link to comment
Share on other sites

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!?

Link to comment
Share on other sites

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&nbsp;Qty',
              'attribute_pa_variation' => 'Variation',
              'sku' => 'SKU',
              'variation_description' => 'Var&nbsp;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>

 

Capture.PNG

Link to comment
Share on other sites

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?

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.