I would like to make a shortcode, that can be placed on category pages, for example on the sidebar.
It should display the category's best selling products.
The only solution that I find is if I specify the category, with slug or id, like below:
[best_selling_products category=”KITCHEN-ACCESSORIES” columns="1" per_page="5"]
How can I transform the shortcode to something like this?
[best_selling_products category=”CURRENT-CATEGORY” columns="1" per_page="5"]
Add this to your functions.php
function custom_best_selling_products( $attr = array() ){
$string = '[best_selling_products ';
$string .= ' category="' . get_query_var( 'term' ) . '" ';
if( $attr ){
foreach ( $attr as $key => $value ) {
$string .= ' ' . $key . '="' . $value . '" ';
}
}
$string .= ']';
return do_shortcode( $string );
}
add_shortcode( 'custom_best_selling_products', 'custom_best_selling_products' );
This will create a custom shortcode and you can use it like this: [custom_best_selling_products columns="1" per_page="5"]
This shortcode will automatically get the category
Add the follows code snippet in your active theme's functions.php to get best selling products from current $term or category page -
function modify_woocommerce_shortcode_products_query( $query_args, $attributes, $type ) {
if( $type != 'best_selling_products' ) return $query_args;
$term = get_queried_object();
if( $term ) {
if( !isset($query_args['category'] ) ){
$query_args['category'] = $term->slug;
}
}
return $query_args;
}
add_filter( 'woocommerce_shortcode_products_query', 'modify_woocommerce_shortcode_products_query', 99, 3 );
Add just use woocommerce default shortcode [best_selling_products columns="1" per_page="5"] to get the data.
Related
I'm building a shop in WP + WooCommerce. I have different types of product categories like discs and bags. For discs products I have some specific attributes like Speed, Glide, Turn and Fade that don't have any other product categories. I want to display these product attribute values only on shop pages under the product picture.
I have found one code for that and I added myself a separation symbol "|", but this separation symbol is now displayed under all the products that are variable.
Is it possible to change the code not to variables but only for specific product categories and sub-categories?
Code:
add_action( 'woocommerce_before_shop_loop_item_title', 'display_size_attribute', 5 );
function display_size_attribute() {
global $product;
if ( $product->is_type('variable') ) {
$taxonomy = 'pa_speed';
echo '<span class="attribute-speed">' . $product->get_attribute($taxonomy) . '</span>' ;
echo ' | ';
$taxonomy = 'pa_Glide';
echo '<span class="attribute-Glide">' . $product->get_attribute($taxonomy) . '</span>';
echo ' | ';
$taxonomy = 'pa_Turn';
echo '<span class="attribute-Turn">' . $product->get_attribute($taxonomy) . '</span>';
echo ' | ';
$taxonomy = 'pa_Fade';
echo '<span class="attribute-Fade">' . $product->get_attribute($taxonomy) . '</span>';
}
}
Use the following revisited code instead to get separated attribute values only if they exist on your variable products:
add_action( 'woocommerce_before_shop_loop_item_title', 'display_some_attributes', 5 );
function display_some_attributes() {
global $product;
if ( $product->is_type('variable') ) {
$attributes = array('speed', 'Glide', 'Turn', 'Fade'); // here you defined attribute slugs
$output = array(); // Initializing
// Loop through product attributes
foreach ( $attributes as $attribute ) {
$taxonomy = 'pa_' . $attribute;
$values = $product->get_attribute($taxonomy);
// If not empty add it to the array
if ( ! empty($values) ) {
$output[] = '<span class="attribute-' . $attribute . '">' . $values . '</span>';
}
}
// Convert array to a separated string by pipes
echo implode(' | ', $output);
}
}
To target specific product categories only, replace in the code the block:
global $product;
if ( $product->is_type('variable') ) {
with (where you will define your product categories terms):
global $product;
$categories = array( 'cats', dogs' ); // Here your category terms ids, slugs or names
if ( $product->is_type('variable') && has_term( $categories, 'product_cat', $product->get_id() ) ) {
Code goes in functions.php file of the active child theme (or active theme). Tested and works.
I keep searching for a way to do this, but I can't find anything unfortunately.
I an trying to display all the product's attributes and values, separated by a pipe, in a custom place on the single-product (so for that I was thinking to create a shortcode, so I can place it anywhere I want). the output would be something like this:
BRAND: RENAULT | MODEL: 12 | YEAR: 1973
The code on the Woocommerce template product-attributes.php lists the attributes of the current product on single-product page, but it will list it with some styles I don't want in a place I don't want.
I want to create a shortcode with that code, which is:
<?php foreach ( $product_attributes as $product_attribute_key => $product_attribute ) : ?>
<?php echo wp_kses_post( $product_attribute['label'] ); ?>: <?php echo wp_kses_post( $product_attribute['value'] ); ?> |
<?php endforeach; ?>
How can I create a shortcode with it? I know the general code for a shortcode, but I don't know how to actually integrate the above one in it:
function custom_attributes_product_page() {
// integrate the required code
// Output needs to be return
return
}
// register shortcode
add_shortcode('custom-attributes', 'custom_attributes_product_page');
Would be great if this shortcode would list the attributes and their values separated by a column, like I said above (how to do that?)
Any help is highly appreciated.
Try the following shortcode that will display all product attribute(s) set for a product and their value(s), handling custom attributes too:
function get_product_attributes_shortcode($atts ) {
// Extract shortcode attributes
extract( shortcode_atts( array(
'id' => get_the_ID(),
), $atts, 'display-attributes' ) );
global $product;
if ( ! is_a($product, 'WC_Product') ) {
$product = wc_get_product( $id );
}
if ( is_a($product, 'WC_Product') ) {
$html = []; // Initializing
foreach ( $product->get_attributes() as $attribute => $values ) {
$attribute_name = wc_attribute_label($values->get_name());
$attribute_data = $values->get_data();
$is_taxonomy = $attribute_data['is_taxonomy'];
$option_values = array(); // Initializing
// For taxonomy product attribute values
if( $is_taxonomy ) {
$terms = $values->get_terms(); // Get attribute WP_Terms
// Loop through attribute WP_Term(s)
foreach ( $terms as $term ) {
$term_link = get_term_link( $term, $attribute );
$option_values[] = ''.$term->name.'';
}
}
// For "custom" product attributes values
else {
// Loop through attribute option values
foreach ( $values->get_options() as $term_name ) {
$option_values[] = $term_name;
}
}
$html[] = '<strong>' . $attribute_name . '</strong>: ' . implode(', ', $option_values);
}
return '<div class="product-attributes">' . implode(' | ', $html) . '<div>';
}
}
add_shortcode( 'display-attributes', 'get_product_attributes_shortcode' );
Code goes in functions.php file of the active child theme (or active theme). Tested and works.
USAGE: [display-attributes] or with a defined product Id [display-attributes id="254"]
You will get a display like: BRAND: RENAULT | MODEL: 12 | YEAR: 1973
If you don't want the linked terms, replace:
$term_link = get_term_link( $term, $attribute );
$option_values[] = ''.$term->name.'';
by this:
$option_values[] = $term->name;
I am trying to have it so for specific product attribute that contain "agave" text is displayed in the short description.
I have tried a few snippets of code but none seem to work. I have no problem getting them to work with Categories but I just want it for certain attributes of the products - Agave
function filter_woocommerce_short_description( $post_excerpt ) {
global $post;
if ( has_term( "agave", "categories", $post->ID ) ) {
$post_excerpt .= "<br/>" . "Text Here";
}
return $post_excerpt;
};
add_filter('woocommerce_short_description', 'filter_woocommerce_short_description',10, 1 );
I expect the text to show up under the certain attributes (Agave) but they do not
I have tried to use this
add_filter('woocommerce_short_description',
'filter_woocommerce_short_description',10, 1 );
function filter_woocommerce_short_description( $short_description ) {
global $product;
$string_values = $product->get_attribute('agave');
if ( strpos($string_values, 'agave') !== false ) {
$short_description .= '<br>' . __("Testing This Out - AGAVE");
}
return $short_description;
}
For a specific product attribute "agave" you will use something a bit different:
add_filter('woocommerce_short_description', 'filter_woocommerce_short_description',10, 1 );
function filter_woocommerce_short_description( $short_description ) {
global $product;
$string_values = $product->get_attribute('agave');
if ( ! empty($string_values) ) {
$short_description .= '<br>' . __("Text Here");
}
return $short_description;
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
Now if "agave" is a term of a product attribute, you should need to set the product attribute name in $product->get_attribute('attribute-name');
and replace the condition by something like:
if ( strpos($string_values, 'agave') !== false ) {
Note: The taxonomy for product category is product_cat, but not categories…
add_filter('woocommerce_short_description', 'filter_woocommerce_short_description',10, 1 );
function filter_woocommerce_short_description( $short_description ) {
global $product;
$string_values = $product->get_attribute('agave');
$agave = $attributes["agave"];
if ( $agave ) {
$short_description .= '<br>' . __("Testing This Out - AGAVE");
}
return $short_description;
}
I need to show different product categories on several regular pages but can't find a suitable shortcode for that.
Which shortcode do I have to use to show only single product category (without showing any products from that category) on any page?
Any help is appreciated.
I think that what you are asking is to get the link from a product category to display the linked product category name. For that you can build a custom shortcode:
add_shortcode('linked_pcat', 'display_a_linked_product_category');
function display_a_linked_product_category( $atts ) {
$atts = shortcode_atts( array(
'term' => '',
), $atts, 'linked_pcat' );
$taxomomy = 'product_cat';
$value = $atts['term'];
if( is_numeric( $value ) || (string) (int) $value == $value ) {
$field = 'term_id';
$value = (int) $atts['term'];
} else {
$field = 'slug';
$value = sanitize_title( $atts['term'] );
}
if( term_exists( $value, $taxomomy ) ) {
$term = get_term_by( $field, $value, $taxomomy );
$term_link = get_term_link( $term, $taxomomy );
return '' . $term->name . '';
}
return false;
}
Code goes in function.php file of the active child theme (or active theme). Tested and works.
USAGE:
Note: For the product category term can use a term name, a term slug or a term ID…
1) In the Wordpress Text Editor (with a term name for example):
[linked_pcat term='Clothing']
2) Inside php code (with a term slug for example):
echo do_shortcode( "[linked_pcat term='t-shirts']" );
3) In a php file between html code (with a term Id for example):
<?php echo do_shortcode( "[linked_pcat term='t-shirts']" ); ?>
Is it possible to remove the first word from the product title in WooCommerce? I've found some php code but I can't figure it out at the moment.
echo substr(strstr("Remove First Word"," "), 1);
That should echo "First Word". How would I do that for the WooCommerce product title? I appreciate all the help!
For product title in single product pages and archives pages:
add_filter( 'the_title', 'custom_the_title', 10, 2 );
function custom_the_title( $title, $post_id ){
$post_type = get_post_field( 'post_type', $post_id, true );
if( $post_type == 'product' || $post_type == 'product_variation' )
$title = substr( strstr( $title, ' ' ), 1 );
return $title;
}
Code goes in function.php file of your active child theme (or active theme).
Tested and works.
The product title uses WordPress function get_the_title() or the_title() to be displayed (as woocommerce product is a custom post type)… so the correct filter hook to be used is "the_title".
But it will not really handle html tags (as this are something else in the templates).
For cart and checkout pages:
add_filter( 'woocommerce_cart_item_name', 'customizing_cart_item_name', 10, 3);
function customizing_cart_item_name( $item_name, $cart_item, $cart_item_key ) {
$product = $cart_item['data'];
$product_permalink = $product->is_visible() ? $product->get_permalink( $cart_item ) : '';
$product_name = $product->get_name();
$product_name = substr( strstr( $product_name, ' ' ), 1 );
if ( $product_permalink && is_cart() ) {
return sprintf( '%s', esc_url( $product_permalink ), $product_name );
} elseif ( ! $product_permalink && is_cart() ) {
return $product_name . ' ';
} else {
return $product_name;
}
}
Code goes in function.php file of your active child theme (or active theme).
Tested and works.
use this:
$str = "Remove First Word";
$words = explode(' ', $str);
unset($words[0]);
echo join(' ', $words);
The explode function returns an array with each words.
The unset function remove the first word contained in the array $words.
Finally, join print all $words joined by space .
demo
Could you try using this?
if ( ! function_exists( 'woocommerce_template_loop_product_title' ) ) {
/**
* Removes first word in WooCommerce product_title
* #var $tag
*/
function woocommerce_template_loop_product_title() {
$tag = is_product_taxonomy() || is_shop() ? 'h2' : 'h3';
echo apply_filters( 'woocommerce_template_loop_product_title', '<' . $tag . ' class="woocommerce-loop-product__title">' . substr(strstr(get_the_title()," "), 1) . '</' . $tag . '>');
}
/**
* Removes first word in WooCommerce product page product_title
* #var $tag
*/
function woocommerce_single_product_summary() {
$tag = 'h1';
echo apply_filters(woocommerce_single_product_summary, '<' . $tag . ' class="product_title entry-title">' . substr(strstr(get_the_title()," "), 1) . '</' . $tag . '>');
}
}
Hopefully this works out for you, haven't tested it.