skip to Main Content

I’m creating a comparison table, the problem I’m having is that I don’t know how to get the product attribute name and value as an array.

This function is for fields

function fields( $products = array() ) {
    $fields = array(
        'thumbnail' => esc_html__( 'Image', 'woocommerce' ),
        'name' => esc_html__( 'Product', 'woocommerce' ),
        'sku' => esc_html__( 'SKU', 'woocommerce' ),
        'price' => esc_html__( 'Price', 'woocommerce' ),
        'rating' => esc_html__( 'Rating', 'woocommerce' ),
    );
    $fields = array_filter( $fields );
    foreach ( $fields as $key => $value ) {
        if ( isset( $this->default_fields[ $key ] ) ) {
            $fields[ $key ] = $this->default_fields[ $key ];
        } elseif ( taxonomy_exists( $key ) ) {
            $fields[ $key ] = wc_attribute_label( $key );
        }
    }
    if ( ! empty( $products ) ) {
        foreach ( $products as $product_id ) {
            $product = wc_get_product( $product_id );
            if ( ! $product ) {
                continue;
            }
            if ( $product instanceof WC_Product_Variation ) {
                $parent_product = wc_get_product( $product->get_parent_id() );
                $attrs          = $parent_product->get_attributes();
            } else {
                $attrs = $product->get_attributes();
            }
            foreach ( $attrs as $key => $value ) {
                $key = urldecode( $key );
                if ( ! isset( $value['is_taxonomy'] ) || ( $value['is_taxonomy'] && ! array_key_exists( $key, $fields ) ) || ( $value['is_taxonomy'] ) || ( ! $value['is_taxonomy'] ) ) {
                    continue;
                }
                $fields[ $key ] = wc_attribute_label( $key, $product );
            }
        }
    }
    return $fields;
}

This is the code that I put in the comparison sheet

<?php foreach ( $fields as $field => $name ) : ?>
    <tr class="<?php echo ! in_array( $field, $different, true ) ? esc_attr( $field ) : esc_attr( $field ) . ' different'; ?>">
        <th>
            <?php echo esc_html( $name ); ?>
        </th>
        <?php
        $index = 0;
        foreach ( $products as $product_id => $product ) :
            // Set td class.
            $product_class = ( ( 0 === ( $index % 2 ) ) ? 'odd' : 'even' ) . ' product_' . $product_id;
            if ( 'stock' === $field ) {
                $availability   = $product->get_availability();
                $product_class .= ' ' . ( empty( $availability['class'] ) ? 'in-stock' : $availability['class'] );
            }
            ?>
            <td class="<?php echo esc_attr( $product_class ); ?>">
                <?php
                    switch ( $field ) {
                        default:
                            echo empty( $product->fields[ $field ] ) ? '-' : do_shortcode( $product->fields[ $field ] );
                            break;
                    }
                ?>
            </td>
            <?php
            ++ $index;
        endforeach
        ?>
    </tr>
<?php endforeach; ?>

thumbnail, name, sku, price, rating values ​​of each product are correctly displayed on the comparison page. But I don’t know how to display the attribute name and value of the products, For example, I have a attribute named pa_gender, and if I put it in the first code as shown below, it displays that attribute correctly.

$fields = array(
    'thumbnail' => esc_html__( 'Image', 'woocommerce' ),
    'name' => esc_html__( 'Product', 'woocommerce' ),
    'sku' => esc_html__( 'SKU', 'woocommerce' ),
    'price' => esc_html__( 'Price', 'woocommerce' ),
    'rating' => esc_html__( 'Rating', 'woocommerce' ),
    'pa_gender' => esc_html__( 'Gender', 'woocommerce' ),
);

But well, I may have thousands of attributes or want to add them, so I can’t enter them all, how can I loop inside the field array and list them all as an array?

update : For example, I want it to be like this, but it gives an error.

$fields = array(
    'thumbnail' => esc_html__( 'Image', 'woocommerce' ),
    'name' => esc_html__( 'Product', 'woocommerce' ),
    'sku' => esc_html__( 'SKU', 'woocommerce' ),
    'price' => esc_html__( 'Price', 'woocommerce' ),
    'rating' => esc_html__( 'Rating', 'woocommerce' ),
    foreach ( wc_get_attribute_taxonomies() as $attribute ) {
        'pa_' . $attribute->attribute_name  => esc_html__( 'pa_name', 'woocommerce' ),
    }
);

My knowledge of programming is little, so if my question is a beginner, please don’t diss.

2

Answers


  1. Chosen as BEST ANSWER

    2 arrays can be combined using the array_merge() function.

    Our first array is as below, which is used for information other than product attributes :

    $fields = array(
        'thumbnail' => esc_html__( 'Image', 'woocommerce' ),
        'name' => esc_html__( 'Product', 'woocommerce' ),
        'sku' => esc_html__( 'SKU', 'woocommerce' ),
        'price' => esc_html__( 'Price', 'woocommerce' ),
        'rating' => esc_html__( 'Rating', 'woocommerce' ),
    );
    

    Our second array is used to get the attributes of the products :

    $attributes           = array();
    $attribute_taxonomies = wc_get_attribute_taxonomies();
    foreach ( $attribute_taxonomies as $attribute ) {
        $tax = wc_attribute_taxonomy_name( $attribute->attribute_name );
        if ( taxonomy_exists( $tax ) ) {
            $attributes[ $tax ] = ucfirst( $attribute->attribute_label );
        }
    }
    

    Well, now these 2 arrays can be combined and converted into one array :

    $fields = array_merge( $fields, $attributes );
    

    After much effort, I came to this conclusion.


  2. You can’t call a foreach statement within the definition of the array.

    So first, you need to define $fields:

    $fields = array(
        'thumbnail' => esc_html__( 'Image', 'woocommerce' ),
        'name' => esc_html__( 'Product', 'woocommerce' ),
        'sku' => esc_html__( 'SKU', 'woocommerce' ),
        'price' => esc_html__( 'Price', 'woocommerce' ),
        'rating' => esc_html__( 'Rating', 'woocommerce' ),
    );
    

    Then insert the additional values, based on the foreach logic:

    foreach ( wc_get_attribute_taxonomies() as $attribute ) {
        $fields['pa_' . $attribute->attribute_name] = esc_html__( 'pa_name', 'woocommerce' );
    }
    

    Alternatively (but only if it suits the way you will use $fields later), you might want to structure your array a bit differently, so you’re not using the pa_ prefix, but instead have a nested array:

    $fields = array(
        'thumbnail' => esc_html__( 'Image', 'woocommerce' ),
        …,
        'product_attributes' => array(),
    );
    
    foreach ( wc_get_attribute_taxonomies() as $attribute ) {
        $fields['product_attributes'][$attribute->attribute_name] = esc_html__( 'pa_name', 'woocommerce' );
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search