How to debug cart content in WooCommerce? - php

Found the following code in another thread:
<?php
global $woocommerce;
$items = $woocommerce->cart->get_cart();
foreach($items as $item => $values) {
$_product = wc_get_product( $values['data']->get_id());
echo "<b>".$_product->get_title().'</b> <br> Quantity: '.$values['quantity'].'<br>';
$price = get_post_meta($values['product_id'] , '_price', true);
echo " Price: ".$price."<br>";
}
?>
I'm a rookie when it comes to adding code.
Simple question: Where do I add this php code?
I have a test site, and would like to see the cart data (in order to try add some other customized code).
Will it simply print onto the page? Will it replacing the standard cart view? Can I view both?
Optimally it would open a new small browser window or gadget to show the "raw" data.

To add custom code to your site you first need to create a child theme. Then, you will need to insert the custom code inside the functions.php file of your active (child) theme.
If it's a staging/debug site you can use the woocommerce_before_cart hook to print the contents of the variables. Another check that you could add is to check if the current user is an administrator, so as not to see the data to other users of the site.
So it will be something like this:
add_action( 'woocommerce_before_cart', 'wc_cart_debug' );
function wc_cart_debug( $cart ) {
if ( ! current_user_can('administrator') ) {
return;
}
// Your code here.
}
RELATED ANSWERS
How to debug in WooCommerce 3
PHP and WordPress: Debugging
How to debug php code while developing wordpress plugins?
Debugging in PHP and Wordpress
Which is the best way to debug PHP in WordPress?

Related

Display an ACF field values in WooCommerce product archive loop

i'm currently playing around on localhost since i'm going to design an ecommerce for a client who owns a records store. I've installed Elementor, WooCommerce and ACF, and at first tried to use elementor custom skin to create a custom loop for my products, where i easily added the field i wanted with dynamic data.
However, this turned out to be a nightmare since being a post archive i lost the sorting etc and also for some reason the add to cart button behaved weirdly (it took me to the single product page after clicking it).
So i've ditched that custom posts archive and used the classic product archive instead, which doesn't allow me to add anything to the product loop directly.
I tried adding this code in my functions.php file (my custom field is named vinyl_genre and it's part of a custom field group):
add_action( 'woocommerce_after_shop_loop_item_title', 'custom_field_display_below_title', 2 );
function custom_field_display_below_title(){
global $product;
// Display ACF text
if( $text = get_field( 'vinyl_genre', $product->get_id() ) ) {
echo '<p class="archive-genre">' . $text . '</p>';
}
}
But it didnt work, instead below each product title in the archive i get this warning:
Warning: : Array to string conversion in [...] \wp-content\themes\hello-theme-child-master\functions.php on line 36 Array
I'm an absolute n00b at php, but i found the above example here on stack and just changed the field name, but to no avail.
Any advice?
-- EDIT --
Using print_r($text) gives an array of values (because vinyl can have multiple genres)
That means that your custom field value is an array with multiple values.
Instead use the following:
add_action( 'woocommerce_after_shop_loop_item_title', 'custom_field_display_below_title', 2 );
function custom_field_display_below_title(){
global $product;
$values = (array) get_field( 'vinyl_genre', $product->get_id() ); // Get custom field values
// Display custom field values
if( ! empty($values) ) {
echo '<p class="archive-genre">' . implode( ', ', $values ) . '</p>';
}
}
Code goes in functions.php file of the active child theme (or active theme). It should work.

Hide Button only on External/Affiliate Product Page / NOT in shop

I would like to hide all buttons only for Eternal/Affiliate and only on the produce page
TLDR
On my site I have a few Pricing tables where the customer can select the appropriate one and then add that item to the cart.
The issue is trying to make an empty product where you cannot purchase it but the pricing table is in the description. So I had to user Eternal/Affiliate product. Which works perfectly as the URL is the product page itself which is great for the shop.
The issue is on the product page you can see a button which says add to cart.
I would like to hide this button only for Eternal/Affiliate and only on the produce page.
You see I already have this code below but obviously I do not want to restrict it to ID numbers and variable products.
Update
so the code below works but if I put a URL link in on the product page then it does not work. Unfortunately now a little bit stumped.
What would be great is if I could remove the button and replace it with some text for example please read below.
function woocommerce_add_aff_link(){
$product = wc_get_product(get_the_ID());
if ($product->is_type('external'))
echo '<a href="' .
$product->get_product_url() .
'" class="woocommerce-LoopProductImage-link">';
}
Update +
After some digging around I found that it is actually more logical to create a new product however the solution below works perfectly:
Reference : https://www.businessbloomer.com/woocommerce-how-to-create-a-new-product-type/
To remove add to cart button on single external product pages use the following:
add_action( 'woocommerce_single_product_summary', 'remove_external_product_add_to_cart_button', 4 );
function remove_external_product_add_to_cart_button(){
global $product;
if ( ! is_a($product, 'WC_Product') ) {
$product = wc_get_product(get_the_ID());
}
if ( $product->is_type('external') ) {
remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_add_to_cart', 30 );
}
}
Code goes in functions.php file of the active child theme (or active theme). TIt should work.

How to clear the woocommerce cart when visiting the particular page (outside of wordpress) custom php page

I am having the woocommerce store like : example.com/store/
And I am creating the some product sales page in outside of wordpress : example.com/upsell.php
Now I want to clear the cart once you visit the example.com/upsell.php, because we are having multiple step in the upsell and finally we are send a url request to add the products in the cart (example.com/store/cart/?add-to-cart=1,5,8).
Whenever you visit the upsell page we need to clear the cart session.
How can clear the cart session from the upsell page?
You need to add an action that will clear cart items in template redirect hook.
In the custom function, check the current page slug & then clear the cart as per our condition.
Use the below code snippet in your theme's functions.php or custom plugin file.
add_action( 'template_redirect', 'woocommerce_clear_cart_url' );
function woocommerce_clear_cart_url() {
global $post;
$slug = $post->post_name;
if($slug == 'sample-page') {
global $woocommerce;
$woocommerce->cart->empty_cart();
}
}
Update
If you don't like hard coding the page slug, there is also a better method.
add_action( 'init', 'woocommerce_clear_cart_url' );
function woocommerce_clear_cart_url() {
if ( isset( $_GET['clear-cart'] ) ) {
global $woocommerce;
$woocommerce->cart->empty_cart();
}
}
Add the above code in your theme's functions.php file.
Then redirect to a page by adding clear-cart query string in your URL & that will clear all cart items.
We can use this function in any URL.
http://example.com?clear-cart
or
http://example.com/sample-page/?clear-cart
I'd use $_SERVER['REQUEST_URI'] to get the current URL of the page so you can test whether you're on the upsell page.
You'll need to use the following function to clear the cart
global $woocommerce;
$woocommerce->cart->empty_cart();
you need to create web api in wp instance which clears cart using this code
global $woocommerce;
$woocommerce->cart->empty_cart();
and call that api on upsell.php file. You can even use HTTP_REFERER to check whether user directly hit the upsell.php url or not.

Custom Woocommerce cart add has wrong item count

I'm trying to add a product to a woocommerce cart with a wp_loaded action after I submit a custom add to cart form.
add_action( 'wp_loaded', 'custom_process_form' );
function custom_process_form(){
global $woocommerce;
if(isset($_POST["addcoupon"])){
foreach($_POST as $key=>$value){
if($key=="addcoupon"){
continue;
}
$valarr=explode("_",$key);
if ($valarr[0]=="couponid"){
$woocommerce->cart->add_to_cart($valarr[1],1);
$count++;
}
}
}
}
It works fine except when it first loads, the cart thinks that I added 2 products instead of 1. For some reason, its running WC_Cart->calculate_totals() twice and $this->cart_contents_count is not reset to zero, so the quantity gets twice. (When I reload the page, the cart shows the correct number of items)
What is the correct way to add a product with a custom form? I can't find any examples of this. Am I using the wrong action?
I experimented on my own install and can confirm the same is happening to me. For me calculate_totals() is getting called once by the add to cart process and then again by the WooCommerce Subscriptions plugin getting the cart from the session. Do you have this plugin installed?
That said I don't think calling calculate_totals() is really a problem. The real problem is that $this->cart_contents_count should reset. I got around this by adding this code to functions.php.
function reset_quantities( $cart )
{
$cart->cart_contents_count = 0;
}
add_action( 'woocommerce_before_calculate_totals', 'reset_quantities' );
EDIT: Actually that doesn't work for me. The reason is that the WooCommerce Subscriptions plugin is calling calculate_totals() through the 'woocommerce_before_calculate_totals' action. This prevents other functions on the same action from firing. This is mentioned at this ticket. https://core.trac.wordpress.org/ticket/17817
Try this instead
function reset_quantities( $cart_object )
{
$cart = $cart_object->get_cart();
$cart_object->cart_contents_count = 0;
foreach ( $cart as $cart_item_key => $values ) {
$cart_object->cart_contents_count += $values['quantity'];
}
}
add_action( 'woocommerce_after_calculate_totals', 'reset_quantities', 10, 1 );
EDIT2 I just looked at the latest commit of WooCommerce on Github and calculate_totals() has changed a lot. You may want to try downloading that to see if it solves your problem.

Conditional WooCommerce Confirmation/Order Received Page based on Product or Category?

I have two distinct products in a WooCommerce cart. One is a ticket, the other is a fee that must be paid before the user can upload a file (which is being handled by a Gravity Form I've created).
Currently, if I put the link to the page with the Gravity Form on the Order Received page, if someone purchases just a ticket, they would see this link and it would be confusing.
Is there a way to either have unique confirmation pages once a purchase is complete based on the product purchased?
If not, are there conditional tags or some kind of hook or filter that would only show the link to the Gravity Form on the Order Received page if the "fee product" is purchased (possibly based on product ID or category ID)?
I did find this code snippet:
https://sozot.com/how-to-hook-into-woocommerce-to-trigger-something-after-an-order-is-placed/
But when I try this:
add_action('woocommerce_payment_complete', 'custom_process_order', 10, 1);
function custom_process_order($order_id) {
$order = new WC_Order( $order_id );
$myuser_id = (int)$order->user_id;
$user_info = get_userdata($myuser_id);
$items = $order->get_items();
foreach ($items as $item) {
if ($item['product_id']==154) {
echo '<h3>If you are submitting a script, please click here to submit your script.</h3>';
}
}
return $order_id;
}
Nothing gets displayed on the Order Details screen. Oddly enough, if I try and use wp_redirect and force a redirect the page, it "works", but it breaks the page and causes some strange embedding of the site within the checkout page.
After beating on this incessantly, I finally found what I was looking for, so I thought I'd post it. In my case, I wanted to customize the Order Detail/Confirmation page with a link to a form, but only when a certain product is purchased.
If you want something similar, put this in the order_details.php template:
global $woocommerce;
$order = new WC_Order( $order_id );
/* This two lines above should already exist, but I have them here so you can
see where to put the code */
foreach($order->get_items() as $item) {
$_product = get_product($item['product_id']);
if ($item['product_id']==154) {
// Do what you want here..replace the product ID with your product ID
}
}
I also tested this by inserting a wp_redirect within the if statement and it seemed to work great, so I imagine you could customize this code with a bunch of if/elseif statements that redirect to different landing pages depending on the product purchased! Hopefully this helps someone!

Categories