Woocommerce adds the assigned product categories and attributes as custom classes to li.product
<li class="post-120 product type-product status-publish has-post-thumbnail
category1 category2 category3 category4 pa_one pa_two...">
We have assigned quite a lot of categories to each product and it slows down the site. Is there a way to remove those additional classes?
In the woocommerce plugin '3.6.2' the file 'wc-template-functions.php' it says:
// Note, to change classes you will need to use the newer woocommerce_post_class filter.
So to remove 'first' & 'last' classes I used:
add_filter( 'woocommerce_post_class', 'remove_post_class', 21, 3 ); //woocommerce use priority 20, so if you want to do something after they finish be more lazy
function remove_post_class( $classes ) {
if ( 'product' == get_post_type() ) {
$classes = array_diff( $classes, array( 'last','first' ) );
}
return $classes;
}
For product categories I used:
add_filter( 'product_cat_class', 'remove_category_class', 21, 3 ); //woocommerce use priority 20, so if you want to do something after they finish be more lazy
function remove_category_class( $classes ) {
if ( 'product' == get_post_type() ) {
$classes = array_diff( $classes, array( 'last','first' ) );
}
return $classes;
}
If you know php, You can edit the woocoommerce php template file to remove those additional classes.
If you opened the file, there is a php variable to be added additional classes and it is a array.
I would suggest applying a filter to the post_class function instead of editing the template as woocommerce updates these regularly and can be a pain to keep on top of them. To do this you could check to see if you in the product loop or if a product exists to also remove from the product page like this :
add_filter( 'post_class', function($classes){
$product = wc_get_product();
return ($product) ? array('product' 'or-any-class-you-want') : $classes; } , 9999 );
Related
I would like to loop throught all products in shop/category page and add special css class to product if it is featured. I have tried to do this with add_filter hook but it seems I am to dumb to get it working.
You were right about using a filter. I don't know which filter you were trying but you would edit the post_class and add a class if the post type is a product and has the specific category you want.
add_filter( 'post_class', 'namespace_featured_posts' );
function namespace_featured_posts( $classes ) {
if( 'product' == get_post_type() && has_term( 'featured', 'product_cat') ) {
$classes[] = 'featured-post';
return $classes;
}
}
In shop, some products belong to multiple categories. This makes default WooCommerce ordering not working, because if one product is first in category A then other product can't be first in category B if both belong to the same category.
I want to find a way to sort products in shop categories by post id in particular order I want ( I will supply IDs).
So far I came up with:
add_filter( 'woocommerce_get_catalog_ordering_args', 'my_ordering_function', 20, 1 );
function my_ordering_function( $args ) {
$product_category = 'my-category';
if( ! is_product_category($product_category) ) return $args;
$args['post__in'] = array( 74, 116, 3565, 3563 );
$args['orderby'] = 'post__in';
$args['order'] = 'ASC';
return $args;
}
This code should do the job, but after examining woocommerce_get_catalog_ordering_args source code, it looks like post__in is not even supported.
Any ideas on how to dictate my own product order per category?
With your approach, you can do this in the parent function of the function that uses the woocommerce_get_catalog_ordering_args filter.
The function you are looking for is product_query, in this function you have an action hook woocommerce_product_query. For your use case, something like this would work.
function my_ordering_function( $q, $this ) {
$q->set( 'post__in', array( 74, 116, 3565, 3563 ) );
$q->set( 'orderby', 'post__in' );
}
add_action( 'woocommerce_product_query', 'my_ordering_function', 10, 2 );
P.S. This function is also in the same file that you referenced. You can have a look there to see how it works.
I noticed that post tags are different than WooCommerce product tags.
I need to add post tags to WooCommerce products so i can include some WooCommerce products in the post tag archives.
Is this possible?
I've tried these code snippets but it doesn't add them.
add_filter( 'pre_get_posts', 'add_custom_types' );
function add_custom_types( $query ) {
if ( is_tag() && empty( $query->query_vars['suppress_filters'] ) ) {
$query->set( 'post_type', array( 'post', 'products', 'product' ) );
return $query;
}
}
add_filter('request', 'post_type_tags_fix');
function post_type_tags_fix($request) {
if ( isset($request['tag']) && !isset($request['post_type']) )
$request['post_type'] = array( 'products', 'product' );
return $request;
}
I needed to do this as well and have come up with what I think is a good way of doing this. A few steps:
Firstly, you need to add the post_tag taxonomy to the woocommerce product post type. You can do this easily with the following filter:
function custom_wc_add_post_tags( $args ){
$args['taxonomies'] = array('post_tag');
return $args;
}
add_filter( 'woocommerce_register_post_type_product', 'custom_wc_add_post_tags' );
This will add a new 'Tags' item to your admin menu, and allow you to tag products with regular post tags rather that the woocommerce-specific 'product_tag' taxonomy. Secondly, you'll likely want to remove the 'product_tag' taxonomy if you don't plan on using it? Because the above will result in two admin menu items called 'tags' which will get confusing. The following will do that for you:
add_filter('woocommerce_taxonomy_objects_product_tag', '__return_empty_array');
add_filter('woocommerce_taxonomy_args_product_tag', '__return_empty_array');
And to remove the column from the 'Products' table on the backend:
function custom_wc_remove_product_tags_column($columns){
unset( $columns['product_tag'] );
return $columns;
}
add_filter( 'manage_edit-product_columns', 'custom_wc_remove_product_tags_column', 15 );
That will actually add the tags to your products. If you then need these to show up in your archive page, you may still need to modify that page's query to look for posts of type 'product' as well as the standard 'post'. It looks like your function above on the 'pre_get_posts' hook will do that part for you. Hope this helps!
Use below code to get archive page in product tag page. now product tag page use theme archive.php file.
Add Below code in theme functions.php
add_filter( 'template_include', 'woocommerce_product_tag_page_template', 99 );
if ( ! function_exists( 'hcode_post_format_parameter' ) ) {
function woocommerce_product_tag_page_template( $template ) {
if ( is_tax( 'product_tag' ) ) {
get_template_part('archive');
}
return $template;
}
}
In Wordpress Woocommerce I have created a grouped product, with lots of sub products (children) in it. I tried searching everywhere, but I can not find a working solution how to orderby them by either SKU or product name. It seems that it's orderby is generated by "Menu Order" only. Although as I have 30+ sub products in these multiple grouped products, it would be extremely time wasting to order them by Menu Order value.
I tried the following code, but it seems that it worked in WC 2.5, but not 3.0+ .
add_filter( 'woocommerce_grouped_children_args',
'so_22661392_grouped_children_args' );
function so_22661392_grouped_children_args( $args ){
$args['meta_key'] = 'sku';
$args['orderby'] = 'meta_value';
$args['order'] = 'ASC';
return $args;
}
I also searched Google for explanations but could not find any. I tried to clear transients, this doesn't work as well:
WooCommerce>System Status>Tools>Clear Transients
The grouped product can be seen on https://plastmet.ee/uus/toode/umartoru-kork-zzo-pealekaiv/ . The html table should match the children below, but it does not. SKU for children is "563/9005", "567/9005" etc..
Any help would be greatly appreciated!
Hopefully I understand the problem correctly:
If we have overriden the template file single-product/add-to-cart/grouped.php, then we could use e.g.:
if( $grouped_products )
usort( $grouped_products, 'wc_products_array_orderby_title' );
to sort the grouped products by title, instead of the default menu ordering.
We could also unregister:
add_action( 'woocommerce_grouped_add_to_cart', 'woocommerce_grouped_add_to_cart', 30 );
with a custom callback instead.
As a last resort one could override the woocommerce_grouped_add_to_cart() function, e.g. within a plugin, to change the menu ordering.
It's defined as:
if ( ! function_exists( 'woocommerce_grouped_add_to_cart' ) ) {
function woocommerce_grouped_add_to_cart() {
global $product;
$products = array_filter( array_map( 'wc_get_product', $product->get_children() ) );
if ( $products ) {
usort( $products, 'wc_products_array_orderby_menu_order' );
wc_get_template( 'single-product/add-to-cart/grouped.php', array(
'grouped_product' => $product,
'grouped_products' => $products,
'quantites_required' => false,
) );
}
}
}
where one could e.g. use wc_products_array_orderby_title instead.
Currently, WooCommerce Order Items within an order, have the following columns:
Item
Tax Class
Qty
Totals
Tax
See screenshot
What I'm aiming to do is add an extra column (or meta) which has a dropdown field for Product Status.
Does anyone have any ideas on how I might accomplish this?
In case someone else stumbles upon this, I needed to add some custom order meta to the order items meta box on the edit order screen. In 2017 this is how I solved this dilemma.
The file class-wc-meta-box-order-items.php, found under includes/admin/meta-boxes has changed slightly since 2014 but it does include the template file html-order-items.php.
It's in that last file that you will find two undocumented hooks, woocommerce_admin_order_item_headers, which you would use to add your custom column heading text and has access to the $order object and woocommerce_admin_order_item_values, which places your custom content right before the Cost column and has access to $product, $item and $item_id.
So to add a custom column it would look something like this.
add_action( 'woocommerce_admin_order_item_headers', 'pd_admin_order_items_headers' );
function pd_admin_order_items_headers($order){
?>
<th class="line_customtitle sortable" data-sort="your-sort-option">
Custom Title
</th>
<?php
}
where your-sort-option depends on what data you are wanting to sort. I used string-ins in my situation.
Than for the content in each line item you would have.
add_action( 'woocommerce_admin_order_item_values', 'pd_admin_order_item_values' );
function pd_admin_order_item_values( $product, $item, $item_id ) {
//Get what you need from $product, $item or $item_id
?>
<td class="line_customtitle">
<?php //your content here ?>
</td>
<?php
}
There are a few other hooks and filters in that template file that are definitely worth looking at if you need content in different places within that meta-box.
I am in the middle of some major adjustments to this table as well, and I haven't figured it all out yet, but I know this much, if you review the class-wc-meta-box-order-items.php within the plugin directory, you will find this snippet of code:
// List order items
$order_items = $order->get_items( apply_filters( 'woocommerce_admin_order_item_types', array( 'line_item', 'fee' ) ) );
foreach ( $order_items as $item_id => $item ) {
switch ( $item['type'] ) {
case 'line_item' :
$_product = $order->get_product_from_item( $item );
$item_meta = $order->get_item_meta( $item_id );
include( 'views/html-order-item.php' );
break;
case 'fee' :
include( 'views/html-order-fee.php' );
break;
}
do_action( 'woocommerce_order_item_' . $item['type'] . '_html', $item_id, $item );
}
DO NOT EDIT THIS SNIPPET!!!
From here you can begin to see what makes up that table. I believe (from what I know of WooCommerce so far) is you can create a function that hooks in at the filter there: woocommerce_admin_order_item_types();
That's what I would do something like this:
# Admin Panel Updates
add_filter( 'woocommerce_add_order_item_meta', array( $this, 'display_order_item_meta' ), 10, 2 );
public function display_order_item_meta( $order_items ) {
array_push($order_items,'event'); //Not sure how to manipulate this yet
return $order_items;
}
Also it looks like we would need to do something with the action hook (woocommerce_order_item_' . $item['type'] . '_html', $item_id, $item), perhaps something along these lines:
add_filter( 'woocommerce_order_item_event_html', array( $this, 'display_event_item_meta' ), 10, 2 );
public function display_event_item_meta( $item_id, $item) {
switch ( $item['type'] ) {
case 'event' :
include( 'views/html-order-event-item.php' );
break;
}
}
That's my best guess so far, but I'm positive this is the right snippet of code to be dissecting.