0

I have a website that sells gaming related stuff, i need to show some buffs as icons/small images under every product below the product image, on the archive/category page, apparently there is no such option nor plugin on the internet that can help me (i would like to be corrected on this please)

So i am trying to work around this on my own, i have very basic coding knowledge.

They way i am trying to do it is by:

  1. These icons are common to the products but their combinations are unique per product, to make it easy i made them as attributes so i can easily assign them per product.
  2. Installed the variation swatches for woocommerce plugin so attributes can have there own images
  3. Made an attribute and made its sub-attributes as my icons and attached images.
  4. All my products are simple downloadable products so variation swatches for woocommerce is of no help as it only works for variable products, but it gave attributes their own images.
  5. Currently i can output the values on attributes on my product cat/archive page with the following code but not images as i have no idea how to call them.

I can display the attributes and there values using the following code

<?php 

add_action( 'woocommerce_after_shop_loop_item', 'loop_attributes', 20 );
function loop_attributes() {
global $product;

if( ! is_object( $product ) ) { 
    $product = wc_get_product( get_the_id() );
}

$win_val = $product->get_attribute('pa_wins');
$hour_val  = $product->get_attribute('pa_hours');
$badge_val = $product->get_attribute('pa_badges');
$token_val = $product->get_attribute('pa_token');

echo '<img src="' . $token_val . '" class="aligncenter" style="margin-bottom: 20px;" />';

echo '<span class="attrs1"><i style="color:#1c7e5a;" class="fas fa-trophy"></i> Wins:</span>'.'<span 
class="attrs2"> '.$win_val.' </span>';
echo '<span class="attrs1"><i style="color:#1c7e5a;" class="fas fa-hourglass"></i> Hours: 
</span>'.'<span class="attrs2"> '.$hour_val.' </span>';
echo '<span class="attrs1"><i style="color:#1c7e5a;" class="fas fa-ribbon"></i> Badges: 
</span>'.'<span class="attrs2"> '.$badge_val.' </span>';
 }

add_filter( 'woocommerce_hide_invisible_variations', '__return_false' );

 ?>

The code above shows the corresponding attribute name and their values on the product cat/archive page,

The attribute pa_token has images attached to their values,

I want the pa_token to output its attached images instead of values, in the below example the code for pa_token is a representation of what i want its not a working code,

echo '<img src="' . $token_val . '" class="aligncenter" style="margin-bottom: 20px;" />';

I need advice if this is a good approach or is there already a solution for this ? If not then how can i go about calling the images attached to the attributes!

Update 1:

When i put this code

function loop_attributes() {
global $product;

if( ! is_object( $product ) ) {
    $product = wc_get_product( get_the_id() );
}

echo '<pre>', print_r($product->get_attributes(), 1), '</pre>';

$token_val = $product->get_attribute('pa_token');

echo '<pre>', print_r($token_val, 1), '</pre>'; 
}
add_action( 'woocommerce_after_shop_loop_item', 'loop_attributes', 10, 0 );

I get the following output

Array
( 

[pa_token] => WC_Product_Attribute Object
    (
        [data:protected] => Array
            (
                [id] => 9
                [name] => pa_token
                [options] => Array
                    (
                        [0] => 210
                        [1] => 211
                    )

                [position] => 6
                [visible] => 1
                [variation] => 
            )

    )

 )

 a, bb

a, bb are the sub attributes/values that have images attached to them

pa_token-> a - Icon 1, bb - Icon 2

Update 2:

So if i do the following code

var_dump( get_term_meta( 210 ) );

I get the following output, looks like we are heading to the right path

array(6) { ["order_pa_token"]=> array(1) { [0]=> string(1) "0" } 
["product_attribute_image"]=> array(1) { [0]=> string(5) "12706" } 
["image_size"]=> array(1) { [0]=> string(9) "thumbnail" } ["show_tooltip"]=> 
array(1) { [0]=> string(4) "text" } ["tooltip_text"]=> array(1) { [0]=> 
string(3) "aaa" } ["tooltip_image"]=> array(1) { [0]=> string(1) "0" } }

I guess we have the meta now, now what should be the relevant code to only output the images with there tooltips on the category/archive page ?

Update 3:

By updating the code to :

function loop_attributes() {
    global $product;

    if( ! is_object( $product ) ) {
        $product = wc_get_product( get_the_id() );
    }

    // Get Product Variations - WC_Product_Attribute Object
    $product_attributes = $product->get_attributes();

    // Not empty, contains values
    if ( !empty( $product_attributes ) ) {

        foreach ( $product_attributes as $product_attribute ) {
            // Get options
            $attribute_options = $product_attribute->get_options();

            // Not empty, contains values
            if ( !empty( $attribute_options ) ) {

                foreach ($attribute_options as $key => $attribute_option ) {
                    // WP_Term Object
                    $term = get_term($attribute_option); // <-- your term ID

                    echo '<pre>', print_r($term, 1), '</pre>';
                }
            }
        }
    }
}
add_action( 'woocommerce_after_shop_loop_item', 'loop_attributes', 10, 0 );

i get the below output

<pre>
WP_Term Object
(
    [term_id] => 210
    [name] => a
    [slug] => aa
    [term_group] => 0
    [term_taxonomy_id] => 210
    [taxonomy] => pa_token
    [description] => 
    [parent] => 0
    [count] => 2
    [filter] => raw
)
</pre>

<pre>
WP_Term Object
(
    [term_id] => 211
    [name] => bb
    [slug] => bb
    [term_group] => 0
    [term_taxonomy_id] => 211
    [taxonomy] => pa_token
    [description] => 
    [parent] => 0
    [count] => 2
    [filter] => raw
)
</pre>

Update 4:

So i was not able to solve my problem earlier, then i switched the plugin to Category and Taxonomy Image by Aftab Hussain and used the following code to call images on the category/archive loop page:

add_action( 'woocommerce_after_shop_loop_item', 
'attribute_img_loop', 20 );
 function attribute_img_loop() {
 global $product;

// Check that we got the instance of the WC_Product object, to be sure (can 
be removed)
if( ! is_object( $product ) ) { 
    $product = wc_get_product( get_the_id() );
}

$token_imgs = get_the_terms( get_the_ID(), 'pa_token');

foreach ( (array) $token_imgs as $token_img ) {
$terms = $token_img->term_id;

    $meta_image = get_wp_term_image($terms); 
echo '<ul><li><img src="' . $meta_image . '" class="tokenimg" " /></li> 
</ul>';
}
}

pa_token is my attribute with sub attributes that have images

foreach loop is used to output all the sub attributes used per product, otherwise it will output only the first result.

(array) inside foreach loop is used to not return anything if the value is null, otherwise all the other products with no attributes get an ugly php debug error on the main page, let me know if there is a non hack way to handle this.

Thanks for your help guys for giving me the right direction.

  • Instead of the variation swatches plugin, why not use ACF? It'd be easier for you to get the term icon and other term metadata. – Sally CJ Mar 23 at 0:22
  • well i tried but by default we don't have images for attributes in woocommerce, and with ACF i will need to define all 30-40 icons per product, i solely used variation swatches as it gives me the option to set images for attributes, i could not get that option with custom hooks i found on the internet, secondly this website will be operated by someone who has no idea about these things, so i am trying to make it easier on the users end. defining these icons through attributes seems to be the easiest as the user can easily select the required icons per product thanks :) – ulvayaam Mar 23 at 13:14
  • Or maybe i am overlooking something obvious and easy :@ – ulvayaam Mar 23 at 13:30
  • Alright then, but as I already pointed, the attribute images are likely saved as term meta, so based on the dump output in the question, you could do var_dump( get_term_meta( 210 ) ); to find the relevant meta. But if you downloaded a plugin from WordPress.org, then you could ask on the plugin's support forums - someone experienced with the plugin, if not the author, might be able to help you. – Sally CJ Mar 24 at 1:32
  • I just edited my main question with the output, for var_dump( get_term_meta( 210 ) ); @SallyCJ – ulvayaam Mar 25 at 8:38
1

So I was not able to solve my problem earlier, then I switched the plugin to "Category and Taxonomy Image" (by Aftab Hussain) and used the following code to display the icons on category/archive pages:

add_action( 'woocommerce_after_shop_loop_item', 'attribute_img_loop', 20 );
function attribute_img_loop() {
    global $product;

    // Check that we got the instance of the WC_Product object, to be sure (can
    // be removed)
    if ( ! is_object( $product ) ) {
        $product = wc_get_product( get_the_ID() );
    }

    $token_imgs = get_the_terms( get_the_ID(), 'pa_token' );

    foreach ( (array) $token_imgs as $token_img ) {
        $terms = $token_img->term_id;

        $meta_image = get_wp_term_image( $terms );
        echo '<ul><li><img src="' . $meta_image . '" class="tokenimg" /></li></ul>';
    }
}
  • pa_token is my attribute with sub-attributes/terms that have images.

  • foreach loop is used to output all the sub-attributes used per product, otherwise it will output only the first result.

  • (array) inside the foreach loop is used to not return anything if the value is null, otherwise all the other products with no attributes get an ugly PHP debug error on the main page.

Thanks for your help guys, for giving me the right direction.

Notes from Sally:

  1. I'd just remove the $product since you don't really need it there because you used get_the_terms() and not a WooCommerce-specific function for getting the pa_token terms.

  2. I don't recommend the (array) $token_imgs. Instead, make sure the $token_imgs is not a WP_Error instance and that it's not an empty array.

  3. Instead of multiple ul (<ul><li></li></ul> <ul><li></li></ul> <ul><li></li></ul>...), I'd use multiple li (<ul><li></li> <li></li> <li></li>...</ul>). :)

So my code would be:

add_action( 'woocommerce_after_shop_loop_item', 'attribute_img_loop', 20 );
function attribute_img_loop() {
    $token_imgs = get_the_terms( get_the_ID(), 'pa_token' );
    if ( ! is_wp_error( $token_imgs ) && ! empty( $token_imgs ) ) {
        echo '<ul>';
        foreach ( $token_imgs as $term ) {
            $meta_image = get_wp_term_image( $term->term_id );
            echo '<li><img src="' . $meta_image . '" class="tokenimg" /></li>';
        }
        echo '</ul>';
    }
}
|improve this answer|||||
  • I hope you don't mind I revised the answer and hopefully the notes help you. :) Cheers! – Sally CJ Mar 30 at 22:44
  • 1
    Not at all this is awesome and works as i needed in a much cleaner way! thanks man!! – ulvayaam Apr 3 at 15:30
0

I don't use the plugin you use for adding images. You can run the following code, this will give you more information about where to find the path to the image.

function loop_attributes() {
    global $product;

    if( ! is_object( $product ) ) {
        $product = wc_get_product( get_the_id() );
    }

    // Get Product Variations - WC_Product_Attribute Object
    $product_attributes = $product->get_attributes();

    // Not empty, contains values
    if ( !empty( $product_attributes ) ) {

        foreach ( $product_attributes as $product_attribute ) {
            // Get options
            $attribute_options = $product_attribute->get_options();

            // Not empty, contains values
            if ( !empty( $attribute_options ) ) {

                foreach ($attribute_options as $key => $attribute_option ) {
                    // WP_Term Object
                    $term = get_term($attribute_option); // <-- your term ID

                    echo '<pre>', print_r($term, 1), '</pre>';
                }
            }
        }
    }
}
add_action( 'woocommerce_after_shop_loop_item', 'loop_attributes', 10, 0 );
|improve this answer|||||
  • Hi, thank you for the code, i have edited my main question with the output – ulvayaam Mar 23 at 13:28
  • Take a look at the progress :) @7uc1f3r – ulvayaam Mar 25 at 9:07
  • I have adjusted my answer, can you continue with that? – 7uc1f3r Mar 25 at 13:30
  • I have updated my original question with your updated code! i still have no clue, sorry i am not good with advanced coding and fetching data from nested arrays :( – ulvayaam Mar 25 at 14:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.