I am accessing archive-products.php on woocommerce to display my products (like the normal process in woocommerce).
On the page of archive-products.php I have added the sidebar with all the product categories that my shop has (with or without products). I have used the following code to do so:
$taxonomy = 'product_cat';
$orderby = 'ID';
$show_count = 0; // 1 for yes, 0 for no
$pad_counts = 0; // 1 for yes, 0 for no
$hierarchical = 1; // 1 for yes, 0 for no
$title = '<h2>' . _x('Our Products', 'mfarma') . '</h2>';
$hide_empty = 0;
$args = array(
'taxonomy' => $taxonomy,
'orderby' => $orderby,
'order' => 'ASC',
'show_count' => $show_count,
'pad_counts' => $pad_counts,
'hierarchical' => $hierarchical,
'title_li' => $title,
'hide_empty' => $hide_empty
);
?>
<ul>
<?php wp_list_categories($args); ?>
</ul>
Now the left side of the page has the above sidebar and the right one has the products. In each product category I have added a small description with an html format that I want to show when the user has clicked the category. According to woocommerce when you go to a specific category (in my case, http://localhost/product-category/mycategory) it is still the archive-products.php.
I am trying to get the term_id from the link clicked, but the loop (and the global $post) points me to the first product of the list instead of the category that I need. So if a category has zero products, I can't get the term ID. How do I get that term ID from archive-products.php?
Found the answer for something else but it also applies to my question.
add_action('woocommerce_archive_description', 'woocommerce_category_description', 2);
function woocommerce_category_description() {
if (is_product_category()) {
global $wp_query;
$cat = $wp_query->get_queried_object();
echo "CAT IS:".print_r($cat,true); // the category needed.
}
}
You can do it simplier:
Print current category:
single_cat_title(); // this prints your current category
Get current category string:
single_cat_title('', false); // this returns your current category
echo single_cat_title('', false); // for print current category
Related
I would like to show subcategory list in a short code.
I like if shortcode will be like [football_subcategory]
I want all list all sub category in a list
You can get it like this:
add_shortcode('football_subcategory', 'football_subcategory');
function football_subcategory(){
$taxonomies = array(
'event_cat',
);
$args = array(
'parent' =>1625, //put your parent category ID
'hide_empty' => false, // you can make it true and false
// 'child_of' => $parent_term_id,
);
$terms = get_terms($taxonomies, $args);
//add a loop and get all details about category
echo '<pre>';
print_r($terms);
}
I am building an e-commerce website and I have installed the following plugin (Customer reviews for Commerce - https://wordpress.org/plugins/customer-reviews-woocommerce/) for Reviews and Ratings of Orders once user completes the order process.
However, the nature of the products we deal with (like fabrics, dresses, sarees etc.) will run out of stock and the same product will not be available again to procure. So, I would want to display the reviews and ratings of old orders using the 'tags' of the products which the order had (For this reason, I would like to have review at order line item). Further, the new product page should fetch the reviews and ratings using it's own tags from old orders which had the same tags.
Any guidance would be helpful in this matter!
To approach this problem, first thing to do is to get all tags associated with a given product into an array. And then, WP_Comments_Query needs to be queried with the array of product ids generated in the first step.
Here is a snippet with the above mentioned approach.
function get_reviews_by_tags(){
global $product;
$productid = $product->get_id();
// get all product_tags of the current product in an array
$current_tags = get_the_terms( $productid, 'product_tag' );
//only start if we have some tags
if ( $current_tags && ! is_wp_error( $current_tags ) ) {
//get all related product ids mapped by tags array we created earlier
$relatedproductids_by_tags = get_posts( array(
'post_type' => 'product',
'numberposts' => -1,
'post_status' => 'publish',
'fields' => 'ids',
'tax_query' => array(
array(
'taxonomy' => 'product_tag',
'field' => 'term_id',
'terms' => $current_tags,
'operator' => 'IN'
)
),
));
// create a wp comment query object as wc uses comments for reviews
$reviews_args = array(
'post__in' => $relatedproductids_by_tags
);
$reviews_query = new WP_Comment_Query;
$reviews = $reviews_query->query( $reviews_args );
if ( !empty( $reviews ) ) {
foreach ( $reviews as $review ) {
echo '<p>' . $review->comment_content . '</p>';
}
} else {
echo 'No reviews found.';
}
}
add_action( 'woocommerce_after_single_product_summary', 'get_reviews_by_tags', 10, 2 );
}
The above code does not consider any modifications being made by the plugin you mentioned in your question. Also, please note that this code is for fetching and displaying reviews as mentioned in your question. This is not for creating reviews.
we have a woocommerce shop for bike parts.
Our parent category name is "Motorcycle-Parts". Subcategories are the motorcycle brands, like:
Motorcycle-Parts
=> Suzuki
=> Honda
=> Yamaha
...
Inside the subcategories, we have the products. These products have an attribute called "ccm" (its the cubic capacity,with numeric values).
Now we try to list all existing "ccm" values from the products of each category underneath the category name, like:
Motorcycle-Parts
=> Suzuki
- 300
- 380
- 550
- ...
=> Honda
- 600
- 650
- 700
- ...
=> Yamaha
- 420
- 650
- 860
- ...
So, if for example a product is inside the category "Suzuki" with the attribute pa_ccm (e.g. 500), we want to automatically list that value (500) underneath the category name, so people see, that inside the category Suzuki one (or more) Products exist that have the pa_ccm value 500.
I tried a few things with _get_term_hierarchy, but my skills are limited here. So no results.
Thanks for help and ideas.
You may have to loop each category, each product, each attribute and then each term in order to get the desired structure. For the purpose of clarity, I am leaving parent-child category part and presenting rest of the code as below:
// Get all categories
$args = array(
'taxonomy' => 'product_cat',
'orderby' => 'name'
);
$all_categories = get_categories($args); //all categories are stored here.
foreach ($all_categories as $cat) {
echo "Category: " .$cat->name ."<br>";
$product_args = array(
'category' => $cat->slug;
);
//get products for each category
foreach( wc_get_products($product_args) as $product ) {
//get attributes for each product
foreach( $product->get_attributes('pa_ccm') as $attr_name => $attr ){
//get terms for each attribute
foreach( $attr->get_terms() as $term ){
echo "CCM: " .$term->name ."<br>";
}
}
}
}
So this is what I have now - Working!
// Get all categories
$args = array(
'taxonomy' => 'product_cat',
'orderby' => 'name',
'parent' => 8543
);
$all_categories = get_categories($args); //all categories are stored here.
foreach ($all_categories as $cat) {
echo "<br><br>Category: " .$cat->name ."<br>";
$product_args = array(
'category' => $cat->slug,
'limit' => -1
);
//get products for each category and hide duplicate term->names
$unique_term_names = array();
foreach( wc_get_products($product_args) as $product ) {
// The attribute slug
$attribute = 'pa_hubraum';
// Get attribute term names in a coma separated string
$term_names = $product->get_attribute( $attribute );
if( ! in_array( $term_names, $unique_term_names ) ) :
// add to array so it doesn't repeat
$unique_term_names[] = $term_names;
echo '<p>' . $term_names . '</p>';
endif;
}
}
This code does list the $term_names from attribute "ccm" underneath the categories and hides duplicate values/term->names.
Last little problem:
As we have many products in these categories with alot of attributes and terms, I want to ask if there is a more performand way to optimise that function/query above?
Does someone have an idea if its possible to programm that in a way to make the loading time faster?
How can I get a serial number of current post in category?
For ex. I have a category Cars with 4 posts in it. When I open some post I want to see navigation like this: Post 3 of 4 [<<] [>>]
Most straightforward way is querying the posts in the category, like this:
// WP_Query arguments
$args = array (
'category_name' => 'cars',
'posts_per_page' => '-1',
'order' => 'DESC',
'orderby' => 'date',
);
// The Query
$query = new WP_Query( $args );
Then you can get the number of posts with
// $query->found_posts gives the number of posts the query has found
// with the parameters you set
echo $query->found_posts;
And you can count up the post you display:
$count = 0;
foreach ( $query->posts as $count_post ) {
$count++;
// assuming you are inside The Loop
if ( get_the_ID() == $count_post->ID ) {
break;
}
}
// now you can get the "serial number" of the post
echo $count;
This might not be the most "WP way" of doing it, but it should work. :)
I've got two custom post types, for example 'Cars' and 'Bikes'. I've used Wordpress's default category to categorise the posts from the two post types. Let's say for example the categories are 'Red', 'Blue' and 'Black'.
What I'm trying to achieve here is that when I go to the category page for 'Red', I want to see the 'Cars' and the 'Bikes' that are categorised under 'Red'. I'm using the category.php and this is the query that I'm trying to run:
$car_args = array(
'posts_per_page' => -1,
'orderby' => 'date',
'order' => 'DESC',
'post_type' => 'cars',
'post_status' => 'publish',
'cat' => $cat
);
// The Query
$car_query = new WP_Query( $car_args );
// The Loop
if ( $car_query ->have_posts() ) {
echo "<h3>Cars</h3>";
while ( $car_query->have_posts() ) {
$car_query->the_post();
echo get_post_type() . '' . get_the_title() . '<br />';
}
} else {
// no posts found
}
$bikes_args = array(
'posts_per_page' => -1,
'orderby' => 'date',
'order' => 'DESC',
'post_type' => 'bikes',
'post_status' => 'publish',
'cat' => $cat
);
// The Query
$bikes_query = new WP_Query( $bikes_args );
// The Loop
if ( $bikes_query ->have_posts() ) {
echo "<h3>Bikes</h3>";
while ( $bikes_query->have_posts() ) {
$bikes_query->the_post();
echo get_post_type() . '' . get_the_title() . '<br />';
}
} else {
// no posts found
}
/* Restore original Post Data */
wp_reset_postdata();
The $cat in the query gets the category id of 'Red' category. Both these queries are correctly restricting the posts by the 'Red' category but posts from both the 'Cars' post type and 'Bikes' post type are showing up even though I've tried to restrict by post type. I've read in a few articles that Wordpress ignores the post type args on the category page. Is this true and if it is, is there a workaround for this?
What you are trying to do is possible with one query only, and only with the main query without any custom queries.
First of all, lets first add your custom post types to your category page. By default, custom pist types are excluded from category pages. So we need to add this manually to the main query arguments via pre_get_posts. Add the following to your functions.php: (CAVEAT: Untested and also requires PHP 5.3+)
add_action( 'pre_get_posts', function ( $q )
{
if ( !is_admin() && $q->is_main_query() && $q->is_category() ) {
$q->set( 'post_type', array( 'post', 'cars', 'bikes' ) ); // Change this according to your post types
$q->set( 'nopaging', true ); // This will get all posts, same as posts_per_page=-1
}
});
You should now have all posts from a clicked category is your set post types on your category pages.
Next, wee need to sort out your loops. Delete all your custom queries in category.php and replace it with the default loop. As you would want two block ordered by post type, we will use rewind_posts() so we can run the loop twice
if ( have_posts() ) {
while ( have_posts() ) {
the_post();
if ( $post->post_type == 'cars' ) { //Change accordingly to only show cars in this loop
// Your loop
}
}
rewind_posts();
while ( have_posts() ) {
the_post();
if ( $post->post_type == 'bikes' ) { // Change accordingly to only show bikes
// Your loop
}
}
}
This should now display your posts in two block sorted by post type