Skip to content

Instantly share code, notes, and snippets.

@helgatheviking
Last active October 11, 2022 21:46
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save helgatheviking/5e3bdca9f6dc9d33a7248b2aacb1d6c3 to your computer and use it in GitHub Desktop.
Save helgatheviking/5e3bdca9f6dc9d33a7248b2aacb1d6c3 to your computer and use it in GitHub Desktop.
WooCommerce display a single product add to cart form with [add_to_cart_form]
/**
* NB: updated version available here: https://github.com/helgatheviking/add-to-cart-form-shortcode
*/
/**
* Add [add_to_cart_form] shortcode that display a single product add to cart form
* Supports id and sku attributes [add_to_cart_form id=99] or [add_to_cart_form sku=123ABC]
* Essentially a duplicate of the [product_page]
* but replacing wc_get_template_part( 'content', 'single-product' ); with woocommerce_template_single_add_to_cart()
*
* @param array $atts Attributes.
* @return string
*/
function kia_add_to_cart_form_shortcode( $atts ) {
if ( empty( $atts ) ) {
return '';
}
if ( ! isset( $atts['id'] ) && ! isset( $atts['sku'] ) ) {
return '';
}
$args = array(
'posts_per_page' => 1,
'post_type' => 'product',
'post_status' => 'publish',
'ignore_sticky_posts' => 1,
'no_found_rows' => 1,
);
if ( isset( $atts['sku'] ) ) {
$args['meta_query'][] = array(
'key' => '_sku',
'value' => sanitize_text_field( $atts['sku'] ),
'compare' => '=',
);
$args['post_type'] = array( 'product', 'product_variation' );
}
if ( isset( $atts['id'] ) ) {
$args['p'] = absint( $atts['id'] );
}
$single_product = new WP_Query( $args );
$preselected_id = '0';
// Check if sku is a variation.
if ( isset( $atts['sku'] ) && $single_product->have_posts() && 'product_variation' === $single_product->post->post_type ) {
$variation = new WC_Product_Variation( $single_product->post->ID );
$attributes = $variation->get_attributes();
// Set preselected id to be used by JS to provide context.
$preselected_id = $single_product->post->ID;
// Get the parent product object.
$args = array(
'posts_per_page' => 1,
'post_type' => 'product',
'post_status' => 'publish',
'ignore_sticky_posts' => 1,
'no_found_rows' => 1,
'p' => $single_product->post->post_parent,
);
$single_product = new WP_Query( $args );
?>
<script type="text/javascript">
jQuery( document ).ready( function( $ ) {
var $variations_form = $( '[data-product-page-preselected-id="<?php echo esc_attr( $preselected_id ); ?>"]' ).find( 'form.variations_form' );
<?php foreach ( $attributes as $attr => $value ) { ?>
$variations_form.find( 'select[name="<?php echo esc_attr( $attr ); ?>"]' ).val( '<?php echo esc_js( $value ); ?>' );
<?php } ?>
});
</script>
<?php
}
// For "is_single" to always make load comments_template() for reviews.
$single_product->is_single = true;
ob_start();
global $wp_query;
// Backup query object so following loops think this is a product page.
$previous_wp_query = $wp_query;
// @codingStandardsIgnoreStart
$wp_query = $single_product;
// @codingStandardsIgnoreEnd
wp_enqueue_script( 'wc-single-product' );
while ( $single_product->have_posts() ) {
$single_product->the_post()
?>
<div class="single-product" data-product-page-preselected-id="<?php echo esc_attr( $preselected_id ); ?>">
<?php woocommerce_template_single_add_to_cart(); ?>
</div>
<?php
}
// Restore $previous_wp_query and reset post data.
// @codingStandardsIgnoreStart
$wp_query = $previous_wp_query;
// @codingStandardsIgnoreEnd
wp_reset_postdata();
return '<div class="woocommerce">' . ob_get_clean() . '</div>';
}
add_shortcode( 'add_to_cart_form', 'kia_add_to_cart_form_shortcode' );
@krisko26
Copy link

You`re a god

@helgatheviking
Copy link
Author

helgatheviking commented Jan 15, 2020

I don't know about that... but glad you like the code. I'd totally forgotten about this gist, but have since packaged this up as a plugin:
https://github.com/helgatheviking/add-to-cart-form-shortcode

How did you find this? Maybe someday I should write a blog post about it.

@passatgt
Copy link

passatgt commented Mar 5, 2020

Thanks for this, this got me started and ended up with this for a custom product page, where the image/title comes from the normal product page, but the add to cart form is actually a different product :)

  $base_post = get_post( $base_product->get_id(), OBJECT );
  setup_postdata( $base_post );
  woocommerce_template_single_add_to_cart();
  wp_reset_postdata();

@miguelbp87
Copy link

Niiiiice!!

@helgatheviking
Copy link
Author

@miguelbp87
Copy link

@helgatheviking awesome thankss :))))

@jfheath
Copy link

jfheath commented Apr 14, 2022

Thanks for the great plugin! I would like to make one small modification to this plugin, to facilitate workflow. I'm not familiar with php, so would need some assistance. What would be required to redirect the user to the checkout page after adding the item to the cart? In our application, a user can purchase just the one product at any one time.

@helgatheviking
Copy link
Author

helgatheviking commented Apr 14, 2022

@jfheath better to use this version: https://github.com/helgatheviking/add-to-cart-form-shortcode
it's specifically this line: https://github.com/helgatheviking/add-to-cart-form-shortcode/blob/master/wc-add-to-cart-form-shortcode.php#L78 that is undoing the redirect. Perhaps we could make a shortcode attribute that will control that. I can be persuaded with pizza. :)

@jfheath
Copy link

jfheath commented Oct 11, 2022 via email

@helgatheviking
Copy link
Author

@jfheath I have added a parameter for that in the plugin. See version 3.0.2.

It would be used as [add_to_cart_form id="99" allow_form_action="true"]

If that has been helpful to you, please consider a donation to my sports team.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment