skip to Main Content

Maybe someone could give me a hand resolving this challenge.

I was looking for a solution which would allow me to add products to cart by SKU’s instead of WooCommerce generated ID’s as I would like to use the same products across different CMS systems.

I have stumbled upon the below code, but it seems not to be compatible anymore? Any advice?

<?php
/**
 * Plugin Name: WooCommerce: Add Product to Cart by SKU
 * Plugin URI: http://remicorson.com
 * Description: Just a demo!
 * Version: 1.0
 * Author: Remi Corson
 * Author URI: http://remicorson.com/
 */

if ( ! defined( 'ABSPATH' ) ) {
    exit; // Exit if accessed directly
}



/**
 * WC Product Add to Cart by SKU class
 */
class WC_Add_to_Cart_by_SKU {

    /**
     * Constructor
     */
    public function __construct() {

        define( 'WC_ADD_TO_CART_BY_SKU_VERSION', '1.0' );
        define( 'WC_ADD_TO_CART_BY_SKU_PATH', untrailingslashit( plugin_dir_path( __FILE__ ) ) );
        define( 'WC_ADD_TO_CART_BY_SKU_PLUGIN_URL', untrailingslashit( plugins_url( basename( plugin_dir_path( __FILE__ ) ), basename( __FILE__ ) ) ) );
    }
    
    /**
     * get_product_id_by_product_sku()
     * 
     * Return product ID from product SKU
     */
    public function get_product_id_by_product_sku( $add_to_cart ) {
    
        global $wpdb;
              
        $product_id = $wpdb->get_var( $wpdb->prepare( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key='_sku' AND meta_value='%s' LIMIT 1", $add_to_cart ) );
              
        if ( $product_id ) return $product_id;
                
        return $add_to_cart;
    
    }
    
}

add_filter( 'woocommerce_add_to_cart_product_id', array( new WC_Add_to_Cart_by_SKU(), 'get_product_id_by_product_sku' ) );

Source: https://gist.github.com/corsonr/c02b46bd34a8471327bbf3adee6507c8

2

Answers


  1. please try this one, i have include the filter call inside __constructor:

    <?php
    /**
     * Plugin Name: WooCommerce: Add Product to Cart by SKU
     * Plugin URI: http://remicorson.com
     * Description: Just a demo!
     * Version: 1.0
     * Author: Remi Corson
     * Author URI: http://remicorson.com/
     */
    
    if ( ! defined( 'ABSPATH' ) ) {
        exit; // Exit if accessed directly
    }
    
    
    /**
     * WC Product Add to Cart by SKU class
     */
    class WC_Add_to_Cart_by_SKU {
    
        /**
         * Constructor
         */
        public function __construct() {
    
            define( 'WC_ADD_TO_CART_BY_SKU_VERSION', '1.0' );
            define( 'WC_ADD_TO_CART_BY_SKU_PATH', untrailingslashit( plugin_dir_path( __FILE__ ) ) );
            define( 'WC_ADD_TO_CART_BY_SKU_PLUGIN_URL', untrailingslashit( plugins_url( basename( plugin_dir_path( __FILE__ ) ), basename( __FILE__ ) ) ) );
            
            add_filter( 'woocommerce_add_to_cart_product_id', array(
                $this,
                'get_product_id_by_product_sku'
            ) );
        }
    
        /**
         * get_product_id_by_product_sku()
         *
         * Return product ID from product SKU
         */
        public function get_product_id_by_product_sku( $add_to_cart ) {
    
            global $wpdb;
    
            $product_id = $wpdb->get_var( $wpdb->prepare( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key='_sku' AND meta_value='%s' LIMIT 1", $add_to_cart ) );
    
            if ( $product_id ) {
                return $product_id;
            }
    
            return $add_to_cart;
    
        }
    
    }
    
    new WC_Add_to_Cart_by_SKU();
    
    
    Login or Signup to reply.
  2. There is no need to use a custom SQL query, as you can use the wc_get_product_id_by_sku() WooCommerce function.

    Using this function is much more lighter and effective but also takes into account products that are not in trash. Something your current code doesn’t do.

    So, this snippet will suffice:

    function filter_woocommerce_add_to_cart_product_id( $product_id ) {
        // Retrieves the post type of the current post or of a given post
        if ( get_post_type( $product_id ) === 'product' ) {
            return $product_id;
        } else {
            $sku = $product_id;
        }
    
        // Get product ID by SKU
        $product_id = wc_get_product_id_by_sku( $sku );
    
        return $product_id;
    }
    add_filter( 'woocommerce_add_to_cart_product_id', 'filter_woocommerce_add_to_cart_product_id', 10, 1 );
    

    Note: SKU is assumed to be a numerical value


    As you can read in the note, the above answer will only work for numerical values, to make this work for all SKU values, ​​you can use as custom query string = /?add-to-cart-sku=THE-SKU

    So you get:

    function action_wp_loaded( $url = false ) {
        // Make sure WC is installed and add-to-cart-sku query arg exists
        if ( ! class_exists( 'WC_Form_Handler' ) || ! isset( $_REQUEST['add-to-cart-sku'] ) || ! is_string( $_REQUEST['add-to-cart-sku'] ) ) {
            return;
        }
         
        // Remove WooCommerce's hook, as it's useless
        remove_action( 'wp_loaded', array( 'WC_Form_Handler', 'add_to_cart_action' ), 20 );
    
        wc_nocache_headers();
    
        $product_id        = wc_get_product_id_by_sku( wp_unslash( $_REQUEST['add-to-cart-sku'] ) );
        $was_added_to_cart = false;
        $adding_to_cart    = wc_get_product( $product_id );
    
        if ( ! $adding_to_cart ) {
            return;
        }
    
        $add_to_cart_handler = apply_filters( 'woocommerce_add_to_cart_handler', $adding_to_cart->get_type(), $adding_to_cart );
    
        if ( 'variable' === $add_to_cart_handler || 'variation' === $add_to_cart_handler ) {
            $was_added_to_cart = woo_hack_invoke_private_method( 'WC_Form_Handler', 'add_to_cart_handler_variable', $product_id );
        } elseif ( 'grouped' === $add_to_cart_handler ) {
            $was_added_to_cart = woo_hack_invoke_private_method( 'WC_Form_Handler', 'add_to_cart_handler_grouped', $product_id );
        } elseif ( has_action( 'woocommerce_add_to_cart_handler_' . $add_to_cart_handler ) ) {
            do_action( 'woocommerce_add_to_cart_handler_' . $add_to_cart_handler, $url ); // Custom handler.
        } else {
            $was_added_to_cart = woo_hack_invoke_private_method( 'WC_Form_Handler', 'add_to_cart_handler_simple', $product_id );
        }
    
        // If we added the product to the cart we can now optionally do a redirect.
        if ( $was_added_to_cart && 0 === wc_notice_count( 'error' ) ) {
            $url = apply_filters( 'woocommerce_add_to_cart_redirect', $url, $adding_to_cart );
    
            if ( $url ) {
                wp_safe_redirect( $url );
                exit;
            } elseif ( 'yes' === get_option( 'woocommerce_cart_redirect_after_add' ) ) {
                wp_safe_redirect( wc_get_cart_url() );
                exit;
            }
        }
    }
    // Fire before the WC_Form_Handler::add_to_cart_action callback.
    add_action( 'wp_loaded', 'action_wp_loaded', 15 );
    
    /**
    * Invoke class private method
    *
    * @since 0.1.0
    *
    * @param string $class_name
    * @param string $methodName
    *
    * @return mixed
    */
    function woo_hack_invoke_private_method( $class_name, $methodName ) {
        if ( version_compare( phpversion(), '5.3', '<' ) ) {
            throw new Exception( 'PHP version does not support ReflectionClass::setAccessible()' );
        }
    
        $args = func_get_args();
        unset( $args[0], $args[1] );
        $reflection = new ReflectionClass( $class_name );
        $method = $reflection->getMethod( $methodName );
        $method->setAccessible( true );
        $args = array_merge( array( $reflection ), $args );
        return call_user_func_array( array( $method, 'invoke' ), $args );
    }
    

    Based on: Allow adding multiple products to the cart via the add-to-cart query string & /includes/class-wc-form-handler.php

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search