How to display cart items upsells on WooCommerce checkout page?
I need some help to display the upsells of all the products in my cart on the checkout page, the code below gives me the following error:
Call to a member function get_upsell_ids() on array in…
Here is my function:
function show_cross_sell( $limit = '-1', $columns = 4, $orderby = 'rand', $order = 'desc' ) { global $woocommerce; $items = WC()->cart->get_cart(); if ( ! $items ) { echo 'nothing'; return; } // Handle the legacy filter which controlled posts per page etc. $args = apply_filters( 'woocommerce_upsell_display_args', array( 'posts_per_page' => $limit, 'orderby' => $orderby, 'order' => $order, 'columns' => $columns, ) ); foreach($items as $product) { wc_set_loop_prop( 'name', 'up-sells' ); wc_set_loop_prop( 'columns', apply_filters( 'woocommerce_upsells_columns', isset( $args['columns'] ) ? $args['columns'] : $columns ) ); $orderby = apply_filters( 'woocommerce_upsells_orderby', isset( $args['orderby'] ) ? $args['orderby'] : $orderby ); $order = apply_filters( 'woocommerce_upsells_order', isset( $args['order'] ) ? $args['order'] : $order ); $limit = apply_filters( 'woocommerce_upsells_total', isset( $args['posts_per_page'] ) ? $args['posts_per_page'] : $limit ); // Get visible upsells then sort them at random, then limit result set. $upsells = wc_products_array_orderby( array_filter( array_map( 'wc_get_product', $product->get_upsell_ids() ), 'wc_products_array_filter_visible' ), $orderby, $order ); $upsells = $limit > 0 ? array_slice( $upsells, 0, $limit ) : $upsells; wc_get_template( 'single-product/up-sells.php', array( 'upsells' => $upsells, // Not used now, but used in previous version of up-sells.php. 'posts_per_page' => $limit, 'orderby' => $orderby, 'columns' => $columns, ) ); } }
There are some mistakes in your code… The following will merge all upsells Ids (without duplicates) from cart items, displaying them as a unique upsells block:
function show_items_upsells( $limit = '-1', $columns = 4, $orderby = 'rand', $order = 'desc' ) { $cart = WC()->cart; if ( WC()->cart->is_empty() ) { echo 'nothing'; return; } $upsell_ids = $cart_item_ids = array(); // Loop through cart items foreach( $cart->get_cart() as $cart_item ) { // Merge all cart items upsells ids $upsell_ids = array_merge( $upsell_ids, $cart_item['data']->get_upsell_ids() ); $cart_item_ids[] = $cart_item['product_id']; } // Remove cart item ids from upsells $upsell_ids = array_diff($upsell_ids, $cart_item_ids); $upsell_ids = array_unique($upsell_ids); // Remove duplicated Ids // Handle the legacy filter which controlled posts per page etc. $args = apply_filters( 'woocommerce_upsell_display_args', array( 'posts_per_page' => $limit, 'orderby' => $orderby, 'order' => $order, 'columns' => $columns, )); wc_set_loop_prop( 'name', 'up-sells' ); wc_set_loop_prop( 'columns', apply_filters( 'woocommerce_upsells_columns', isset( $args['columns'] ) ? $args['columns'] : $columns ) ); $orderby = apply_filters( 'woocommerce_upsells_orderby', isset( $args['orderby'] ) ? $args['orderby'] : $orderby ); $_order = apply_filters( 'woocommerce_upsells_order', isset( $args['order'] ) ? $args['order'] : $order ); $limit = apply_filters( 'woocommerce_upsells_total', isset( $args['posts_per_page'] ) ? $args['posts_per_page'] : $limit ); // Get visible upsells then sort them at random, then limit result set. $upsells = wc_products_array_orderby( array_filter( array_map( 'wc_get_product', $upsell_ids ), 'wc_products_array_filter_visible' ), $orderby, $_order ); $upsells = $limit > 0 ? array_slice( $upsells, 0, $limit ) : $upsells; wc_get_template( 'single-product/up-sells.php', array( 'upsells' => $upsells, // Not used now, but used in previous version of up-sells.php. 'posts_per_page' => $limit, 'orderby' => $orderby, 'columns' => $columns, ) ); }
Code goes in function.php file of your active child theme (or active theme). Tested and works.
USAGE: echo show_items_upsells();