I'm using Wordpress with WooCommerce, I've made a custom theme (so possibly part of the problem) but I've based it off the default Wordpress theme.
When I click on a product page that doesn't have ANY pictures, the layout is fine and it shows a blank picture image.
When I then add an image to the same product, refresh the page product page, the layout style for the tabs disappears and instead the tabs are displayed as text with no style. It appears that the ::before and ::after code is present on the "no image" tabs, but when I add an image they disappear!
The style for the image also changes, the size goes crazy and there is no padding on the right of the image so the description/title/add to cart touches the image!
Site: http://frenchies-boutique.wadessolutions.com
The site was build around the Twenty Fifteen theme.
single-product.php
<?php
/**
* The Template for displaying all single products.
*
* Override this template by copying it to yourtheme/woocommerce/single-product.php
*
* #author WooThemes
* #package WooCommerce/Templates
* #version 1.6.4
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
get_header( 'shop' ); ?>
<?php
/**
* woocommerce_before_main_content hook
*
* #hooked woocommerce_output_content_wrapper - 10 (outputs opening divs for the content)
* #hooked woocommerce_breadcrumb - 20
*/
do_action( 'woocommerce_before_main_content' );
?>
<?php while ( have_posts() ) : the_post(); ?>
<?php wc_get_template_part( 'content', 'single-product' ); ?>
<?php endwhile; // end of the loop. ?>
<?php
/**
* woocommerce_after_main_content hook
*
* #hooked woocommerce_output_content_wrapper_end - 10 (outputs closing divs for the content)
*/
do_action( 'woocommerce_after_main_content' );
?>
<?php
/**
* woocommerce_sidebar hook
*
* #hooked woocommerce_get_sidebar - 10
*/
do_action( 'woocommerce_sidebar' );
?>
<?php get_footer( 'shop' ); ?>
product-image.php
<?php
/**
* Single Product Image
*
* #author WooThemes
* #package WooCommerce/Templates
* #version 2.0.14
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
global $post, $woocommerce, $product;
?>
<div class="images">
<?php
if ( has_post_thumbnail() ) {
$image_title = esc_attr( get_the_title( get_post_thumbnail_id() ) );
$image_caption = get_post( get_post_thumbnail_id() )->post_excerpt;
$image_link = wp_get_attachment_url( get_post_thumbnail_id() );
$image = get_the_post_thumbnail( $post->ID, apply_filters( 'single_product_large_thumbnail_size', 'shop_single' ), array(
'title' => $image_title,
'alt' => $image_title
) );
$attachment_count = count( $product->get_gallery_attachment_ids() );
if ( $attachment_count > 0 ) {
$gallery = '[product-gallery]';
} else {
$gallery = '';
}
echo apply_filters( 'woocommerce_single_product_image_html', sprintf( '%s', $image_link, $image_caption, $image ), $post->ID );
} else {
echo apply_filters( 'woocommerce_single_product_image_html', sprintf( '<img src="%s" alt="%s" />', wc_placeholder_img_src(), __( 'Placeholder', 'woocommerce' ) ), $post->ID );
}
?>
<?php do_action( 'woocommerce_product_thumbnails' ); ?>
</div>
thanks
Related
I used the following code in the file comments.php and it worked for posts only on blog pages ....
<ol class="comment-list">
<?php $user_id = get_current_user_id();
$user_comments = get_comments( array ( 'user_id' => $user_id ));
wp_list_comments(
array(
'style' => 'ol',
'short_ping' => true,
'callback' => 'storefront_comment',
),
$user_comments );
?>
</ol><!-- .comment-list -->
How can I do the same on the product pages? I tried to edit the file woocommerce/templates/single-product/review.php , but I didn't succeed.... Can you tell me how to implement this ?
Here is the code from woocommerce/templates/single-product/review.php
* #package WooCommerce\Templates
* #version 2.6.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
?>
<li <?php comment_class(); ?> id="li-comment-<?php comment_ID(); ?>">
<div id="comment-<?php comment_ID(); ?>" class="comment_container">
<?php
/**
* The woocommerce_review_before hook
*
* #hooked woocommerce_review_display_gravatar - 10
*/
do_action( 'woocommerce_review_before', $comment );
?>
<div class="comment-text">
<?php
/**
* The woocommerce_review_before_comment_meta hook.
*
* #hooked woocommerce_review_display_rating - 10
*/
do_action( 'woocommerce_review_before_comment_meta', $comment );
/**
* The woocommerce_review_meta hook.
*
* #hooked woocommerce_review_display_meta - 10
*/
do_action( 'woocommerce_review_meta', $comment );
do_action( 'woocommerce_review_before_comment_text', $comment );
/**
* The woocommerce_review_comment_text hook
*
* #hooked woocommerce_review_display_comment_text - 10
*/
do_action( 'woocommerce_review_comment_text', $comment );
do_action( 'woocommerce_review_after_comment_text', $comment );
?>
</div>
</div>
You can compare the current user id and early return if it does not match.
On:
{child-theme}/woocommerce/single-product/review.php
Add the following checks:
* #package WooCommerce\Templates
* #version 2.6.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
$user_id = get_current_user_id();
if ( !$user_id ) { return; }
$comment = get_comment( get_comment_ID() );
if ( $user_id !== $comment->user_id ) {
return;
}
?>
<li <?php comment_class(); ?> id="li-comment-<?php comment_ID(); ?>">
We would like to add (fixed) custom text in between the title/label of the product variation and the dropdown selector like indicated below.
We already tried following code
add_filter( 'woocommerce_attribute_label', 'custom_attribute_label', 10, 3 );
function custom_attribute_label( $label, $name, $product ) {
$taxonomy = 'pa_'.$name;
if( $taxonomy == 'pa_bodenankertyp' )
$label .= '<div class="custom-label">' . __('MY custom TEXT', 'woocommerce') . '</div>';
return $label;
}
from this post
Adding a custom text next to a specific product attribute label in WooCommerce
but it does not work.
Any idea or hints what is wrong are appreciated!
I would not recommend using this hook since you change it in multiple places - places where you don't want any changes. I would suggest overwriting the specific WooCommerce template. For that, go to your child theme and create the following folder structure:
your-child-theme/woocommerce/single-product/add-to-cart/
Now you need to create a PHP file named variable.php in there and paste the following code inside:
<?php
/**
* Variable product add to cart
*
* This template can be overridden by copying it to yourtheme/woocommerce/single-product/add-to-cart/variable.php.
*
* HOWEVER, on occasion WooCommerce will need to update template files and you
* (the theme developer) will need to copy the new files to your theme to
* maintain compatibility. We try to do this as little as possible, but it does
* happen. When this occurs the version of the template file will be bumped and
* the readme will list any important changes.
*
* #see https://docs.woocommerce.com/document/template-structure/
* #package WooCommerce\Templates
* #version 3.5.5
*/
defined( 'ABSPATH' ) || exit;
global $product;
$attribute_keys = array_keys( $attributes );
$variations_json = wp_json_encode( $available_variations );
$variations_attr = function_exists( 'wc_esc_json' ) ? wc_esc_json( $variations_json ) : _wp_specialchars( $variations_json, ENT_QUOTES, 'UTF-8', true );
do_action( 'woocommerce_before_add_to_cart_form' ); ?>
<form class="variations_form cart" action="<?php echo esc_url( apply_filters( 'woocommerce_add_to_cart_form_action', $product->get_permalink() ) ); ?>" method="post" enctype='multipart/form-data' data-product_id="<?php echo absint( $product->get_id() ); ?>" data-product_variations="<?php echo $variations_attr; // WPCS: XSS ok. ?>">
<?php do_action( 'woocommerce_before_variations_form' ); ?>
<?php if ( empty( $available_variations ) && false !== $available_variations ) : ?>
<p class="stock out-of-stock"><?php echo esc_html( apply_filters( 'woocommerce_out_of_stock_message', __( 'This product is currently out of stock and unavailable.', 'woocommerce' ) ) ); ?></p>
<?php else : ?>
<table class="variations" cellspacing="0">
<tbody>
<?php foreach ( $attributes as $attribute_name => $options ) : ?>
<tr>
<td class="label">
<label for="<?php echo esc_attr( sanitize_title( $attribute_name ) ); ?>"><?php echo wc_attribute_label( $attribute_name ); // WPCS: XSS ok. ?></label>
<div class="custom-label"><?= __('MY custom TEXT', 'woocommerce') ?></div>
</td>
<td class="value">
<?php
wc_dropdown_variation_attribute_options(
array(
'options' => $options,
'attribute' => $attribute_name,
'product' => $product,
)
);
echo end( $attribute_keys ) === $attribute_name ? wp_kses_post( apply_filters( 'woocommerce_reset_variations_link', '<a class="reset_variations" href="#">' . esc_html__( 'Clear', 'woocommerce' ) . '</a>' ) ) : '';
?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<div class="single_variation_wrap">
<?php
/**
* Hook: woocommerce_before_single_variation.
*/
do_action( 'woocommerce_before_single_variation' );
/**
* Hook: woocommerce_single_variation. Used to output the cart button and placeholder for variation data.
*
* #since 2.4.0
* #hooked woocommerce_single_variation - 10 Empty div for variation data.
* #hooked woocommerce_single_variation_add_to_cart_button - 20 Qty and cart button.
*/
do_action( 'woocommerce_single_variation' );
/**
* Hook: woocommerce_after_single_variation.
*/
do_action( 'woocommerce_after_single_variation' );
?>
</div>
<?php endif; ?>
<?php do_action( 'woocommerce_after_variations_form' ); ?>
</form>
<?php
do_action( 'woocommerce_after_add_to_cart_form' );
In this code you will find your div. If you need any checks, just put them around your div. In your case I would check the variable $attribute_name.
I have created the custom shop page in wooommerce and I removed all the code from then archive-product.php and added the below code and it's displaying the products.
defined( 'ABSPATH' ) || exit;
get_header( 'shop' );
/**
* Hook: woocommerce_before_main_content.
*
* #hooked woocommerce_output_content_wrapper - 10 (outputs opening divs for the content)
* #hooked woocommerce_breadcrumb - 20
* #hooked WC_Structured_Data::generate_website_data() - 30
*/
do_action( 'woocommerce_before_main_content' );
?>
<div class="container">
<div class="products">
<div class="row">
<?php
$args = array(
'post_type' => 'product',
'posts_per_page' => 12
);
$loop = new WP_Query( $args );
if ( $loop->have_posts() ) {
while ( $loop->have_posts() ) : $loop->the_post();
wc_get_template_part( 'content', 'product' );
endwhile;
} else {
echo __( 'No products found' );
}
wp_reset_postdata();
?>
</div>
</div>
</div>
<?php
get_footer( 'shop' );
Now Where I will get the code of this wc_get_template_part( 'content', 'product' ); because I have to change the strcture
Below screenshot is the woocommerce template.
As it's used inside the product loop, the template file that is called in:
wc_get_template_part( 'content', 'product' );
is content_product.php located in the woocommerce plugin folder > templates subfolder (Take a look to the code on HERE).
Note: you can override WooCommerce templates via your active child theme (or active theme) or use all available hooks in the template content_product.php.
For the displayed thumbnail:
You can see on content_product.php template this:
/**
* Hook: woocommerce_before_shop_loop_item_title.
*
* #hooked woocommerce_show_product_loop_sale_flash - 10
* #hooked woocommerce_template_loop_product_thumbnail - 10 // <=== HERE
*/
do_action( 'woocommerce_before_shop_loop_item_title' );
So Image is called via the template function woocommerce_template_loop_product_thumbnail() and that function call woocommerce_get_product_thumbnail() function:
/**
* Get the product thumbnail, or the placeholder if not set.
*
* #param string $size (default: 'woocommerce_thumbnail').
* #param int $deprecated1 Deprecated since WooCommerce 2.0 (default: 0).
* #param int $deprecated2 Deprecated since WooCommerce 2.0 (default: 0).
* #return string
*/
function woocommerce_get_product_thumbnail( $size = 'woocommerce_thumbnail', $deprecated1 = 0, $deprecated2 = 0 ) {
global $product;
$image_size = apply_filters( 'single_product_archive_thumbnail_size', $size );
return $product ? $product->get_image( $image_size ) : '';
}
}
Related: WooCommerce action hooks and overriding templates
With woocommerce on the archive pages, there is a before shop loop that includes pagination.
The pagination is also included after the shop loop so I want to remove it from the top of the page and leave it at the bottom.
This is the archive page code. Removing the before shop loop php code from the top of the page works but breaks the page formatting with the sidebar:
<?php
/** * The Template for displaying product archives, including the main shop page which is a post type archive. * * Override this template by copying it to yourtheme/woocommerce/archive-product.php * * #author WooThemes * #package WooCommerce/Templates * #version 2.0.0 */
if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
get_header( 'shop' ); ?>
<?php
/**
* woocommerce_before_main_content hook
*
* #hooked woocommerce_output_content_wrapper - 10 (outputs opening divs for the content)
* #hooked woocommerce_breadcrumb - 20
*/
do_action( 'woocommerce_before_main_content' );
?>
<?php echo mad_title(array(
'title' => woocommerce_page_title(false)
)); ?>
<?php do_action( 'woocommerce_archive_description' ); ?>
<?php if ( have_posts() ) : ?>
<?php
/**
* woocommerce_before_shop_loop hook
*
* #hooked woocommerce_result_count - 20
* #hooked woocommerce_catalog_ordering - 30
*/
do_action( 'woocommerce_before_shop_loop' );
?>
<?php woocommerce_product_loop_start(); ?>
<?php woocommerce_product_subcategories(); ?>
<?php while ( have_posts() ) : the_post(); ?>
<?php wc_get_template_part( 'content', 'product' ); ?>
<?php endwhile; // end of the loop. ?>
<?php woocommerce_product_loop_end(); ?>
<?php
/**
* woocommerce_after_shop_loop hook
*
* #hooked woocommerce_pagination - 10
*/
do_action( 'woocommerce_after_shop_loop' );
?>
<?php elseif ( ! woocommerce_product_subcategories( array( 'before' => woocommerce_product_loop_start( false ), 'after' => woocommerce_product_loop_end( false ) ) ) ) : ?>
<?php wc_get_template( 'loop/no-products-found.php' ); ?>
<?php endif; ?>
<?php
/**
* woocommerce_after_main_content hook
*
* #hooked woocommerce_output_content_wrapper_end - 10 (outputs closing divs for the content)
*/
do_action( 'woocommerce_after_main_content' );
?>
<?php
/**
* woocommerce_sidebar hook
*
* #hooked woocommerce_get_sidebar - 10
*/
do_action( 'woocommerce_sidebar' );
?>
If anyone can help me work out how to do this i would be grateful.
In the woocommerce config.php the theme developer had added
add_action('woocommerce_before_shop_loop', array(&$this, 'woocommerce_pagination'));
commenting this out resolved the issue.
Ive made a new page template and copied the woocommerce archive-product.php into it but while the shop page works, the custom page does not, is there a way to make it function the same as the shop page? noticed it also does not pull in anything else from visual composer or normal content.
For those who wants custom woocommerce shop template ( archive-product ) here is a sample template, which can be customized to any extent.
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
get_header( 'shop' ); ?>
<?php
/**
* woocommerce_before_main_content hook
*
* #hooked woocommerce_output_content_wrapper - 10 (outputs opening divs for the content)
* #hooked woocommerce_breadcrumb - 20
*/
do_action( 'woocommerce_before_main_content' ); ?>
<?php if ( apply_filters( 'woocommerce_show_page_title', true ) ) : ?>
<h1 class="page-title"><?php woocommerce_page_title(); ?></h1>
<?php endif; ?>
<?php do_action( 'woocommerce_archive_description' ); ?>
<?php
global $post, $product;
$args = array(
'post_type'=>'product',
'posts_per_page'=>-1,
'orderby'=>'date',
'order'=>'ASC'
);
// get all the posts ( here it would be all the wc products )
$posts = get_posts( $args );
/**
* woocommerce_before_shop_loop hook
*
* #hooked woocommerce_result_count - 20
* #hooked woocommerce_catalog_ordering - 30
*/
do_action( 'woocommerce_before_shop_loop' );
if( count( $posts ) > 0 ) {
woocommerce_product_loop_start();
woocommerce_product_subcategories();
foreach( $posts as $post ) {
// this will put the current post into the GLOBAL $post object
setup_postdata( $post );
// this will put the product data into GLOBAL $product object
wc_setup_product_data( $post ); ?>
<!-- Now you have valid WP loop, put the content-product template here -->
<?php wc_get_template_part( 'content', 'product' ); ?>
<?php
}
woocommerce_product_loop_end();
} else {
wc_get_template( 'loop/no-products-found.php' );
}
/**
* woocommerce_after_shop_loop hook
*
* #hooked woocommerce_pagination - 10
*/
do_action( 'woocommerce_after_shop_loop' );
/**
* woocommerce_sidebar hook
*
* #hooked woocommerce_get_sidebar - 10
*/
do_action( 'woocommerce_sidebar' );
get_footer( 'shop' ); ?>