Display product counter only in subcategories - WooCommerce - php

Hello stackoverflow community.
I am trying to get functionality to display a product counter but only in subcategories. In the main categories I want to disable it.
At the moment I have been able to do this:
function add_product_count_view()
{
global $wp_query;
$category_id = $wp_query->get_queried_object()->term_id;
$query = new WP_Query(array(
'tax_query' => array(
array(
'taxonomy' => 'product_cat',
'field' => 'id',
'terms' => $category_id,
'include_children' => true,
),
),
'nopaging' => true,
'fields' => 'ids',
));
if (function_exists("is_shop") && $category_id != 0) {
echo '(' .esc_html($query->post_count) . ')';
}
}
and output
<span class="custom-home-category-counts">
<?php do_action('count_product_title');?>
</span>
This way I got what I want but the counter shows the same value for each subcategory
----UPDATE---- #CBroe
It is possible that all this code is garbage. My knowledge of PHP is quite poor. Generally what I mean is, I want to disable the product counter in main categories and leave only in all subcategories.
This is the original code that renders the product counter.
<?php if (get_theme_mod('category_show_count', 1)) : ?>
<p class="is-xsmall uppercase count">
<?php if ($category->count > 0) {
echo apply_filters('woocommerce_subcategory_count_html', $category->count . ' ' . ($category->count > 1 ? __('Products', 'woocommerce') : __('Product', 'woocommerce')), $category);
}
?>
</p>
<?php endif; ?>

After every custom WP_Query, you need to run wp_reset_postdata() to ensure that global $post is restored to the current post in the main query.
In your code, you can use this function as follows:
function add_product_count_view()
{
global $wp_query;
$category_id = $wp_query->get_queried_object()->term_id;
$query = new WP_Query(array(
'tax_query' => array(
array(
'taxonomy' => 'product_cat',
'field' => 'id',
'terms' => $category_id,
'include_children' => true,
),
),
'nopaging' => true,
'fields' => 'ids',
));
if (function_exists("is_shop") && $category_id != 0) {
echo '(' .esc_html($query->post_count) . ')';
}
wp_reset_postdata(); //reset the main query loop
}
This way, the next time the query runs, it runs with new data. This can be the reason why the counter shows same value for all sub categories.

Related

WooCommerce: Add multiple cross-sell products to the cart at once with ajax

On my product detail page I'm trying to allow users to add multiple cross-sell products to the cart at once.
I found a few examples how this could be done. But most of them work with URL parameters.
For my case I'm trying to do this with ajax. Like the default add-to-cart button.
On my research I found an example here.
But I'm not sure how to adapt it for my case.
At the moment I have a list of product ID's from a custom loop.
Here's my custom loop code:
add_action('woocommerce_single_product_cols_before', 'show_cross_sell_in_single_product', 1200);
function show_cross_sell_in_single_product(){
$crosssells = get_post_meta( get_the_ID(), '_crosssell_ids',true);
$args = array(
'post_type' => 'product',
'posts_per_page'=> -1,
'post__in' => $crosssells,
'tax_query' => array(
array(
'relation' => 'OR',
array(
'taxonomy' => 'product_visibility',
'field' => 'name',
'terms' => 'exclude-from-catalog',
'operator' => 'NOT IN',
),
array(
'taxonomy' => 'product_visibility',
'field' => 'name',
'terms' => 'exclude-from-catalog',
'operator' => '=',
),
)
),
);
$products_crosssells = new WP_Query( $args );
$products_crosssells_ids = wp_list_pluck( $products_crosssells->posts, 'ID' );
if( $products_crosssells->have_posts() ) : ?>
<div>
<ul>
<?php while ( $products_crosssells->have_posts() ) : $products_crosssells->the_post(); ?>
<?php wc_get_template_part( 'content', 'product-crosssells' ); ?>
<?php endwhile; ?>
</ul>
Add all to the cart
</div>
<?php endif;
wp_reset_postdata();
}
The product ID's are stored in $products_crosssells_ids.
As I understand the example from the link above, I need to add the product ID's to the custom function:
add_action('wp_ajax_multi_add_to_cart', 'multi_ajax_add_to_cart');
add_action('wp_ajax_nopriv_multi_add_to_cart', 'multi_ajax_add_to_cart');
function multi_ajax_add_to_cart() {
if (isset($_POST['items']) ) {
$item_keys = array();
foreach( $_POST['items'] as $item ) {
if( isset($item['id']) ) {
$item_qty = isset($item['qty']) && $item['qty'] > 1 ? $item['qty'] : 1;
$item_keys[] = WC()->cart->add_to_cart($item['id'], $item_qty);
}
}
echo json_encode($item_keys); // Send back cart item keys
}
die();
}
But I'm not sure how I need to add/adapt this code to my product page.
So A user could click on this link and adds everything to the cart:
Add all to the cart

Display how many reviews there are for a CPT

I have two custom post types, 'product' and 'product_review'. The CPT 'product_review' has a taxonomy 'product_name' whose slug matches the CPT 'product'
An example 'Product A' is the product post. 'Product Review A' is the product_review post that has a 'product_name' taxonomy value of 'product_a'.
I need to show how many 'product_review' each 'product' has.
<?php
global $post;
$post_slug = $post->post_name;
//echo $post_slug;
//this outputs the name of the product, which I need
$terms = get_terms('product_review');
foreach ( $terms as $post_slug ) {
echo $term->count . 'Reviews';
?>
It doesn't show any count. I want it to show how many $terms(how many reviews) are tied to $post_slug(name of product). The 'product_review' slug matches the slug of the product.
You can use a custom WP_Query and the found_posts prop like below:
// example query args
$args = [
// look for reviews cpt
'post_type' => 'product_review',
// limit to posts that match our taxonomy product name
'tax_query' => [
[
'taxonomy' => 'product_name',
'field' => 'slug',
'terms' => [ 'product_a' ]
]
]
];
// run the query
$query = new WP_Query( $args );
// grab "total" found posts
$total = $query->found_posts;
// display the total
echo $total
// reset post data so we dont break the main loop
wp_reset_postdata();
#mikerojas answer got me close, but wasn't returning accurate data. Here is what I came up with that got me what I needed.
<?php
$review_args = array(
'post_type' => 'my_post_type',
'post_status' => 'publish',
'tax_query' => array(
array (
'taxonomy' => 'my_taxonomy',
'field' => 'slug',
//this is already inside a loop, making it dynamic to only grab the reviews whose tax value equals the post slut
'terms' => $post->post_name,
)
),
);
if($num = count( get_posts ( $review_args)) <= 1) {
echo 'Review ' . $num = count( get_posts( $review_args ) );
} else {
echo 'Reviews ' . $num = count( get_posts( $review_args ) );
}
wp_reset_postdata();
?>

Limit Woocommerce featured products in a WP_Query

I want to get 3 featured products in the header of the site. But my query keeps returning unlimited number of results.
I've been looking online for a solution and came across answers that all answer saying the same thing in terms of the query. What could I be doing wrong?
$meta_query = WC()->query->get_meta_query();
$tax_query = WC()->query->get_tax_query();
$tax_query[] = array(
'taxonomy' => 'product_visibility',
'field' => 'name',
'terms' => 'featured',
'operator' => 'IN',
);
$args = array(
'post_type' => 'product',
'post_status' => 'publish',
'posts_per_page' => 2,
'meta_query' => $meta_query,
'tax_query' => $tax_query,
);
$featured_query = new WP_Query( $args );
if ($featured_query->have_posts()) {
while ($featured_query->have_posts()) :
$featured_query->the_post();
$product = get_product( $featured_query->post->ID );
echo $product->title; echo "test";
// Product info here
endwhile;
}
wp_reset_query();
The following query returned 20 results. The code was placed in header.php. Using woocommerce 3.x.
First your code is a bit outdated, since Woocommerce 3, as get_product() need to be replaced with wc_get_product() and $product->title; by $product->get_title();…
Once done your code works and you will get 3 featured products:
$meta_query = WC()->query->get_meta_query();
$tax_query = WC()->query->get_tax_query();
$tax_query[] = array(
'taxonomy' => 'product_visibility',
'field' => 'name',
'terms' => 'featured',
'operator' => 'IN',
);
$featured = new WP_Query( array(
'post_type' => 'product',
'post_status' => 'publish',
'posts_per_page' => 3, // <== <== <== 3 products
'meta_query' => $meta_query,
'tax_query' => $tax_query,
) );
// Get the products count in the query
echo '<p>Featured products count: ' .$featured->post_count . '</p>';
if ($featured->have_posts()) : while ($featured->have_posts()) :
$featured->the_post();
$product = wc_get_product( $featured->post->ID );
echo $product->get_title() . '<br>';
// Product info here
endwhile; endif;
wp_reset_postdata();
It should work for you as I have tested successfully this code on header.php file…
As before Woocommerce 3, the "featured products" where handled by post meta data (a meta query), you may need to update product terms count going to Woocommerce settings > status > tools. In "Term counts" section click on "Recount terms".
You should be using wp_reset_postdata() instead of wp_reset_query() since WP_query doesn't overwrite the main query.
If that doesn't solve your issue, make sure any other custom loops use the appropriate reset, and/or try renaming the variable $featured_query if you're using it elsewhere - it may be inheriting posts from a previous loop.
You could also try adding the 'nopaging' => true and 'ignore_sticky_posts' => true arguments
I hate to suggest it, but if you can't figure out why it's returning 20 posts instead of 2, you could just break your while loop with a counter:
if ($featured_query->have_posts()) {
$counter = 0;
while ($featured_query->have_posts()) : $featured_query->the_post();
/* Do post stuff here */
$counter++;
if( $counter == 2 ) break;
endwhile;
}

Wordpress Recent Posts/Projects

Hi I have created my own custom post type within Wordpress to contain projects that i can call via my theme files.
I am new to creating my own themes. I currently am using the following code in my single.php file to call in related articles based on the category of the blog post.
<?php
// Default arguments
$args = array(
'posts_per_page' => 3, // How many items to display
'post__not_in' => array( get_the_ID() ), // Exclude current post
'no_found_rows' => true, // We don't ned pagination so this speeds up the query
);
// Check for current post category and add tax_query to the query arguments
$cats = wp_get_post_terms( get_the_ID(), 'category' );
$cats_ids = array();
foreach( $cats as $wpex_related_cat ) {
$cats_ids[] = $wpex_related_cat->term_id;
}
if ( ! empty( $cats_ids ) ) {
$args['category__in'] = $cats_ids;
}
// Query posts
$wpex_query = new wp_query( $args );
// Loop through posts
foreach( $wpex_query->posts as $post ) : setup_postdata( $post ); ?>
<div class="col-md-4 related-post">
<?php the_post_thumbnail('large'); ?>
<?php the_title(); ?>
</div>
<?php
// End loop
endforeach;
// Reset post data
wp_reset_postdata(); ?>
In my new post type "projects" i would like to call in related projects. Which im assuming would be very similar code except i need to stop it looking for posts and instead look for my projects.
Here is my code for new post type:
// Projects
add_action( 'init', 'create_post_type' );
add_post_type_support( 'bw_projects', 'thumbnail' );
add_post_type_support( 'bw_projects', 'custom-fields' );
function create_post_type() {
register_post_type( 'bw_projects',
array(
'labels' => array(
'name' => __( 'Projects' ),
'singular_name' => __( 'Projects' )
),
'public' => true,
'has_archive' => true,
'taxonomies' => array( 'category','post_tag'),
)
);
}
What would i need to change in my first code snippet in order to look for bw_projects and not look for 'posts' anymore. I tried playing around and changing certain lines myself but i caused more issues and stopped the page loading. Is this even right i can use the same code, slightly altered or would i need something completely different?
Thanks in advance.
You can get any post type that you require using get_posts();
<?php $args = array(
'posts_per_page' => 5,
'offset' => 0,
'category' => '',
'category_name' => '',
'orderby' => 'date',
'order' => 'DESC',
'include' => '',
'exclude' => '',
'meta_key' => '',
'meta_value' => '',
'post_type' => 'projects',
'post_mime_type' => '',
'post_parent' => '',
'author' => '',
'author_name' => '',
'post_status' => 'publish',
'suppress_filters' => true
);
$posts_array = get_posts( $args ); ?>
Simply set the 'post_type' argument to that of you custom post type, to get only these posts. You can also set the number of post, and filter by category etc.
You can find more info in the codex.
Alternatively, if you wanted to keep something similar to your existing code you could try using 'pre_get_posts' to filter the query to just your projects. However you'd need to remember to add / remove this filter so it only operates on the queries that need it.
To display the posts you can use a simple foreach to churn them out. You#d obviously want to do some sort of styling to get the layout correct:
$args = array("posts_per_page" => 10, "orderby" => "comment_count");
$posts_array = get_posts($args);
foreach($posts_array as $post)
{
echo "<h1>" . $post->post_title . "</h1><br>";
echo "<p>" . $post->post_content . "</p><br>";
}
Or a really concise way of doing all of the above would be something like:
$args = array("posts_per_page" => 5, "post_type" => "projects");
$posts_array = get_posts($args);
foreach($posts_array as $post)
{
echo "<h1>" . $post->post_title . "</h1><br>";
echo "<p>" . $post->post_content . "</p><br>";
}

how to create loops with multi relation taxanomy queries in wordpress

I'm trying to create a loop that loads posts from a custom taxonomy and a specific category , i have used this code below but it doesn't show anything
<ul class="row">
<?php
$latest_apps = new WP_Query(array(
'post_type' => array('product','post'),
'posts_per_page' => 30,
'tax_query' => array(
'relation' => 'AND',
array(
'taxonomy' => 'category',
'field' => 'id',
'terms' => array( get_option("free_apps_category") )
),
array(
'taxonomy' => 'product_cat',
'field' => 'id',
'terms' => array( get_option("premium_apps_category") )
)
)
));
$c = 0;
while ($latest_apps->have_posts()) : $latest_apps->the_post();
$c++;
// post is even
if( $c % 2 == 0) {
?>
<?php the_post_thumbnail("post"); ?>
</li>
<?php
}
// post is odd
else {
?>
<li class="content-box-post">
<?php the_post_thumbnail("post"); ?>
<?php
}
endwhile;
?>
</ul>
i have used static id numbers instead of get_option('free_apps_category') and get_option('premium_apps_category') but it still does not work
please help , thank u so much
regards
If it does not show you nothing, it is because you have no posts that match your condition.
And reading the code fast One can see that your query is for a post either normal or under product post type that is both on the premium_apps_category AND free_apps_category . Are you sure that you actually have one ?

Categories