Save cart on the current session

2019-02-07 15:06发布

问题:

I'm building a wordpress ecommerce site with the woocommerce plugin, it turns that when an user gets logged in and add products to his cart, but the user don't want to proceed to the checkout process, the user prefers to logout and continue with the checkout process later... when the user comes back and gets logged in again the cart is empty.

What is going on here?. Is this a normal behavior of woocommerce?. Do I have to do something else? maybe a plugin?

Thanks.

回答1:

I thought that the cart is emptied when a user logs out, and I finally tracked it down.

On wp_logout() WordPress runs wp_clear_auth_cookie() function. wp_clear_auth_cookie() triggers the do_action( 'clear_auth_cookie' ); action hook.

WooCommerce's Session handler class then runs it's destroy method on this hook.

add_action( 'clear_auth_cookie', array( $this, 'destroy_session' ) );

The destroy_session() method then calls the wc_empty_cart() function, which is a wrapper for the cart class's empty_cart() method.

WC()->cart->empty_cart( false ); 

But the key thing here is that the parameter is false. Because when we finally track down the empty_cart() method we see that the default is true.

    /**
     * Empties the cart and optionally the persistent cart too.
     *
     * @access public
     * @param bool $clear_persistent_cart (default: true)
     * @return void
     */
    public function empty_cart( $clear_persistent_cart = true ) {
        $this->cart_contents = array();
        $this->reset();

        unset( WC()->session->order_awaiting_payment, WC()->session->applied_coupons, WC()->session->coupon_discount_amounts, WC()->session->cart );

        if ( $clear_persistent_cart && get_current_user_id() ) {
            $this->persistent_cart_destroy();
        }

        do_action( 'woocommerce_cart_emptied' );
    }

When passing true the persistant_cart_destroy() method is called and it is this method that deletes the meta data where the user's cart is kept.

    /**
     * Delete the persistent cart permanently.
     *
     * @access public
     * @return void
     */
    public function persistent_cart_destroy() {
        delete_user_meta( get_current_user_id(), '_woocommerce_persistent_cart' );
    }

SO, all of that is to say that I do not think the cart should be emptied when a user logs out and then back in. A little more evidence is that WooCommerce attempts to load the persistent cart as soon as a user logs back in.

/**
 * Load the cart upon login
 *
 * @param mixed $user_login
 * @param integer $user
 * @return void
 */
function wc_load_persistent_cart( $user_login, $user = 0 ) {

    if ( ! $user )
        return;

    $saved_cart = get_user_meta( $user->ID, '_woocommerce_persistent_cart', true );

    if ( $saved_cart )
        if ( empty( WC()->session->cart ) || ! is_array( WC()->session->cart ) || sizeof( WC()->session->cart ) == 0 )
            WC()->session->cart = $saved_cart['cart'];
}
add_action( 'wp_login', 'wc_load_persistent_cart', 1, 2 );

I would try disabling all other plugins to see if the behavior reverts back to what I think is the normal behavior. From there, you can re-enable them one at a time to isolate the culprit.



回答2:

I faced same problem and solved it by placing following function to my functions.php file:

/**
* Load the persistent cart if exists
*
* @return void
*/
function adian_load_persistent_cart(){

    global $current_user;

    if( ! $current_user )
    return false;

    $saved_cart = get_user_meta( $current_user->ID, '_woocommerce_persistent_cart', true );

    if ( $saved_cart ){
        if ( empty( WC()->session->cart ) || ! is_array( WC()->session->cart ) || sizeof( WC()->session->cart ) == 0 ){
            WC()->session->set('cart', $saved_cart['cart'] );   
        }
    }

}

add_action( 'init', 'adian_load_persistent_cart', 10, 1 );

Function checks if the user has persistent cart saved and replaces session cart with it.