0

I'd like to replace default "Read more" button text on products conditionnaly.

example: if $product_type = 'simple' && category = 'services' return mystring

So fare, I have :

add_filter( 'woocommerce_product_add_to_cart_text' , 'custom_woocommerce_product_add_to_cart_text' );
function custom_woocommerce_product_add_to_cart_text() {

    global $product;

    $product_type = $product->product_type;

    switch ( $product_type ) {
        case 'external':
            return __( 'External text', 'woocommerce' );
        break;
        case 'grouped':
            return __( 'Grouped text', 'woocommerce' );
        break;
        case 'simple':
            return __( 'Simple text', 'woocommerce' );
        break;
        case 'variable':
            return __( 'Variable text', 'woocommerce' );
        break;
        default:
            return __( 'Read more', 'woocommerce' );
    }

}
0

First you should check if you're actually replacing Read more, you can also remove the default: and just make sure you return the original value passed to the filter.

If you specifically want to use switch you can use a less commonly used pattern for evaluating statements by setting switch(true) and then enclosing the if statement in parenthesis for the case

To get/check the categories, there's a couple ways to do this, in my example below i'm using get_the_terms to get all the categories, and then mapping all the slugs to an array, so you can use in_array (i removed the other case statements for simplicity of the example code):

add_filter( 'woocommerce_product_add_to_cart_text', 'custom_woocommerce_product_add_to_cart_text', 10 );

function custom_woocommerce_product_add_to_cart_text( $text ) {

    // First make sure that we are only replacing 'Read more' as some situations based on product
    // this can be "Select some options" or "Add to cart"
    $wc_read_more = __( 'Read more', 'woocommerce' );

    if( $text !== $wc_read_more ){
        return $text;
    }

    global $product;

    $product_type = $product->product_type;
    $product_terms = get_the_terms( $product->ID, 'product_cat' );

    // Convert to array of all the slugs
    $pc_slugs = array_map( function($term){ return $term->slug; }, $product_terms );

    switch ( true ) {
        case ( $product_type === 'simple' && in_array( 'services', $pc_slugs ) ):
            return __( 'Simple text', 'woocommerce' );
            break;
    }

    return $text;
}

Another option would be to use has_term instead of mapping slugs to an array:

add_filter( 'woocommerce_product_add_to_cart_text', 'custom_woocommerce_product_add_to_cart_text', 10, 2 );

function custom_woocommerce_product_add_to_cart_text( $text, $that ) {

    // First make sure that we are only replacing 'Read more' as some situations based on product
    // this can be "Select some options" or "Add to cart"
    $wc_read_more = __( 'Read more', 'woocommerce' );

    if( $text !== $wc_read_more ){
        return $text;
    }

    global $product;

    $product_type = $product->product_type;

    switch ( true ) {
        case ( $product_type === 'simple' && has_term( 'services', 'product_cat', $product->ID ) ):
            return __( 'Simple text', 'woocommerce' );
            break;
    }

    return $text;
}

Also want to mention you said if $product_type = 'simple' && category = 'services', in PHP a single = is assignment, meaning "set equal to", it's good to get in the habit of always using == or === (strict) even if just explaining in laments terms

  • Brilliant, thanks @sMyles for both well explained examples, very usefull. – JackLinkers Feb 16 at 9:30

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.