Please help me.
I'm selling some products in Woocommerce.
I've modified the "sort by" function to make it simple, so it will only sort by price and title. The default sorting is alphabetically (ascending).
But strangely, not all product titles are in order alphabetically. For example, this one:
The "Swe in Black" is supposed to appear before "Tally Ho Fan Back Red", but it appears otherwise.
And this one also:
The last three products are not in order alphabetically. Moreover, there always appears a blank white space before the last product.
Here's my product page link:
cardstory.co/collections
Strange is, this only happens in some browsers (e.g. Firefox, Chrome). But not in Safari.
--
Here's my custom function.php code for product sorting:
<?php
// Edit WooCommerce dropdown menu item of shop page//
// Options: menu_order, popularity, rating, date, price, price-desc
function my_woocommerce_catalog_orderby( $orderby ) {
unset($orderby["popularity"]);
unset($orderby["rating"]);
unset($orderby["date"]);
return $orderby;
}
add_filter( "woocommerce_catalog_orderby", "my_woocommerce_catalog_orderby", 20 );
//Attach function to filter hook
add_filter('woocommerce_catalog_orderby', 'custom_woocommerce_catalog_orderby');
//add new options to $sortby var passed into filter
function custom_woocommerce_catalog_orderby($sortby) {
$sortby['name_asc'] = "Sort by name: A-Z";
$sortby['name_desc'] = "Sort by name: Z-A";
return $sortby;
}
//Attach our function to the filter hook:
add_filter('woocommerce_get_catalog_ordering_args', 'custom_catalog_ordering_args');
//Function to handle choices
function custom_catalog_ordering_args($args) {
global $wp_query;
// Changed the $_SESSION to $_GET
if ($_GET['orderby'] == "name_asc") {
$args['orderby'] = 'title';
$args['order'] = "ASC";
} else if ($_GET['orderby'] == "name_desc") {
$args['orderby'] = 'title';
$args['order'] = "DESC";
}
return $args;
}
I've disabled all plugins for this page but nothing works.
Any help is highly appreciated. Thank you! :)
Related
Is it possible in Woocommerce, if the product category page shows its subcategories, to do any actions? I need to add a class to the body tag on such pages. Is it real? Example:
function my_custom_body_class_woo_cat($classes) {
if ( is_product_category() && is_subcategory_show() ) {
$classes[] = 'my-class';
return $classes;
}
}
add_filter('body_class','my_custom_body_class_woo_cat');`
I tried to look for solutions, but I didn't find one
I checked woocommerce conditional tags and is_subcategory_show() is not a valid woocommerce function.
So in order for this to work we need to do our own checks before assigning the extra class or classes to the body.
Here is a code snippet that does what you asked( if i understood your question correctly ):
add_filter('body_class', function ($classList) {
// Not a product category, return the classList intact
if (!is_product_category()) {
return $classList;
}
$desiredDisplayType = 'subcategories';
$term = get_queried_object();
// Not a parent category, return classList intact
if ($term->parent !== 0) {
return $classList;
}
// Get the woocommerce category archive display option (the one you set up in the customizer)
$categoryArchiveDisplayOption = get_option('woocommerce_category_archive_display');
// Get the display type for the current category
$currentCategoryDisplayOption = get_term_meta($term->term_id, 'display_type', true);
// The current category displatype isn't the desired one, return classList intact
if ($currentCategoryDisplayOption !== $desiredDisplayType) {
return $classList;
}
// Neither of the option are the desired one, return classList intact
if (
$currentCategoryDisplayOption !== $desiredDisplayType
&& $categoryArchiveDisplayOption !== $desiredDisplayType
) {
return $classList;
}
// All checks passed, add my class to body
return array_merge($classList, ['my-class']);
});
Woocommerce has a general option in the customizer where you set up if you want category archives to display subcategories.
Then when you edit a specific category you can assign a display type specific to that category, so this should take precedence over the general option.
I'm using woocommerce shortcode to display custom products loop, e.g. [products limit="-1" paginate="true" orderby="menu_order" columns="5" ids="85,11,1083,256,37,12,517,68,2577,104"]. But there's a problem – they are displaying sorted by title, but I need them to be sorted in that exact order they are in shortcode. I found no such option in shortcodes docs. Is there a way to achieve it with shortcode?
The woocommerce_shortcode_products_query_results hook runs after the products have been queried from the database, but before they are displayed on the page. By hooking into this hook and modifying the order of the results, it is possible to display the products in the desired order.
//Products shortcode custom order by id
add_filter('woocommerce_shortcode_products_query_results', 'bytflow_custom_products_shortcode_order', 10, 2);
function bytflow_custom_products_shortcode_order($results, $shortcode_products){
$attributes = $shortcode_products->get_attributes();
$order_by_arg = get_query_var('orderby');
// Check if there are any ids specified and that user didn't change the order
if (empty($order_by_arg) && ! empty( $attributes['ids'] ) ) {
$ids = explode( ',', $attributes['ids'] );
$ordered_results = array();
foreach ($ids as $id){
if(in_array($id, $results->ids)){
$ordered_results[] = $id;
}
}
$results->ids = $ordered_results;
}
return $results;
}
This code checks for the presence of the ids attribute in the shortcode and, if it exists, rearranges the products in the $results->ids array to match the order specified in the attribute. Source
Solution found: orderby = "post__in"
Source: Woocommerce Product Short Code Order by Order of IDs
I am using "Frontend Submit Pro" and "ACF(not pro) plugins for WordPress.
I am using these plugins to make frontend post creator for my users.
I have more than 200+ categories so I want to make it more easy for my users to select categories. I will create multiple forms and each form will have a few categories to be selected from users.
For now i use the below filter to exclude some categories from forms.
add_filter('acf/fields/taxonomy/query/name=kathgories', 'exclude_categories', 10, 2);
function exclude_categories( $args, $field ) {
global $uncategorized_id;
$args['exclude'] = array(290,287,283,289,281,291,286,280,284,279); //the IDs of the excluded terms
return $args;
}
Because I have a lot of categories I can't exclude 200 categories in the above code is too hard.
So i want a filter that will exclude all categories and include only the 5-10 categories that i want to be show in each form.
I have not the knowledge to do that so i am asking if anyone can help.
I also want each filter apply to only one form. I need some way to link filters to the correct form.(maybe by link or form name)
Solved it with a filter.
add_action( 'init', 'get_term_ids' );
function get_term_ids() {
global $uncategorized_id;
$u = get_term_by( 'slug', 'uncategorized', 'product_cat' );
$uncategorized_id = $u->term_id;
}
add_filter('acf/fields/taxonomy/query/name=kathgories', 'exclude_categories', 10, 2);
function exclude_categories( $args, $field ) {
global $uncategorized_id;
$args['exclude'] = array($uncategorized_id); //the IDs of the excluded terms
return $args;
}
Answering my question.
I changed the "exclude" to "include" in the filter above and it seems to do exactly what I wanted.
It only shows the categories that I give it in the form.
For those who display categories within "select" use the following code.
add_filter('acf/fields/taxonomy/query/name=kathgories', 'include_categories', 10, 2);
function include_categories( $args, $field ) {
global $uncategorized_id;
$args['include'] = array(290,287,283,289,281,291,286,280,284,279); //the IDs of the excluded terms
return $args;
}
For those who display categories in a "checkbox" use the following code.
add_filter('acf/fields/taxonomy/wp_list_categories/name=kathgories', 'my_taxonomy_args', 10, 2);
function my_taxonomy_args( $args, $field ){
$args['include'] = array(197,247,245,250,246,248,249,251);//the IDs of the excluded terms
return $args;
}
Also change /name=kathgories'
with your own ACF Taxonomy field name.
So with that change , I am answering my second question.
Trying to achieve something that should be simple, but I've tried 3 approaches with multiple code variations and I just can't make it work. I'm trying to create a button that will appear in place of the "ADD TO CART" button on single product pages when the item is out of stock. Clicking the button will fire a popup contact form.
Is creating an add action in functions the right way to go, or should I replace the normal button with an if statement? I've tried both, so help with coding either would be greatly appreciated.
You can either hook into woocommerce_loop_add_to_cart_args using a filter in your functions.php or edit the template file directly by pulling it into your theme. Either way will require a bit of PHP.
If doing it in your functions.php, it would look something like this (untested but should send you down the right path):
<?php
add_filter( 'woocommerce_loop_add_to_cart_link', 'my_out_of_stock_button' );
function my_out_of_stock_button( $args ){
global $product;
if( $product && !$product->is_in_stock() ){
return 'Contact us';
}
return $args;
}
I don't know what your button code should actually look like or what other information you need to capture, but this is how you could override the "Add to Cart" button and replace it if out of stock.
UPDATE
LoicTheAztec brought up a great point - the filter provided only affects the button on the archive, category, tag overview pages - not the individual product pages. There are no hooks for the individual product page buttons BUT you can copy the templates to your theme and override them.
You'll want to look at the files in templates/single-product/add-to-cart. Use a similar if statement as above:
#simple.php
<?php if ( $product->is_in_stock() ) : ?>
// Standard WooCommerce code
<?php else: ?>
// Your button code
<?php endif; ?>
Just add below code in functions.php file of your enabled theme reference
add_action('woocommerce_after_shop_loop_item', 'themelocation_change_outofstock_to_contact_us', 1);
// for shop page
function themelocation_change_outofstock_to_contact_us() {
global $product;
if (!$product->is_in_stock()) {
remove_action('woocommerce_after_shop_loop_item', 'woocommerce_template_loop_add_to_cart');
remove_action('woocommerce_single_product_summary', 'woocommerce_template_single_add_to_cart');
//change the link to your contact us page
echo ' Contact Us ';
}
}
// for single page
add_filter('woocommerce_get_availability', 'wcs_custom_get_availability', 1, 2);
function wcs_custom_get_availability($availability, $_product) {
// Change In Stock Text
if ($_product->is_in_stock()) {
$availability['availability'] = __('Available!', 'woocommerce');
}
// Change Out of Stock Text
if (!$_product->is_in_stock()) {
$availability['availability'] = __(' Contact Us ', 'woocommerce');
}
return $availability;
}
I was looking for a way to show a contact button on bespoke products and
#ahwychkchih solution works great. One issue I had though is that schema markup will show as out of stock for those products which is not the case for beskpoke products is just they can't be purchased straight away so I've added this to force in_stock markup for my products. I'm aware that this solution would affect all products so you can always add a product id filter if needed
// Force In Stock schema markup
function fix_my_product_offers_schema ($markup_offer, $product) {
if (!$product->is_in_stock()) {
$markup_offer['availability'] = 'https://schema.org/InStock';
}
return $markup_offer;
}
add_filter('woocommerce_structured_data_product_offer', 'fix_my_product_offers_schema', 1, 2);
I have attributes on all of my products such as "Select your size" and "Select your colour", however in the basket and at checkout I would like to strip "Select your" from all of the attributes so that it is not displayed.
As shown on product page:
As currently shown at checkout, however I really want to remove "Select your":
Is there an easy way to do this in the Woocommerce template files?
fighting away with this will be a battle of the century... you will not just have to remove that string in there... it will also be like that on the email sent and order page will display it. Also some pages I can't remember...
I think you just want the "Select your" string in the product page, is it not?
if so, why not add that string just in there?
So in your variation, in the product admin page, add the variation as size. Then change the display in product page like this:
add_filter('woocommerce_attribute_label','reigel_attribute_label', 10, 2);
function reigel_attribute_label( $label, $name ) {
if (is_product() && $label == 'size') {
$label = 'Select your ' . $label;
}
// another if statement if needed...
if (is_product() && $label == 'color') {
$label = 'Select your ' . $label;
}
return $label;
}
with this approach, you will just have the Select your size in the product page...
You can use WooCommerce's in build API function to do both.
eg.
1. Returns a specific item in the cart.
get_cart_item( $item_key );
https://docs.woothemes.com/wc-apidocs/source-class-WC_Cart.html#751-762
2.Process the checkout after the confirm order button is pressed.
process_checkout();
https://docs.woothemes.com/wc-apidocs/source-class-WC_Checkout.html#343-718
You can take all the reference you need. There are lists of functions are available to do changes.