Woocommerce AJAX API not Posting custom Product fi

2019-08-25 08:56发布

问题:

I have created custom fields for specific products

            //-------------------------- CUSTOM Front FIELD ----------------------

    /*
     * Display input on single product page
     * @return html
     */

    function message_front_note(){
        global $product;

        if ( $product->get_id() !== 451 ) {
            return;
        }
        $value = isset( $_POST['_message_front'] ) ? sanitize_text_field( $_POST['_message_front'] ) : '';
        printf( '<label>%s</label><input class="msg-note wh-input" name="_message_front" value="" maxlength="15" Placeholder="Up to 15 Letters or Numbers" />', __( 'Front', 'shf-custom-msg-front-fields' ), esc_attr( $value ) );
    }

    add_action( 'woocommerce_before_add_to_cart_button', 'message_front_note', 9 );


    /*
     * Validate when adding to cart
     * @param bool $passed
     * @param int $product_id
     * @param int $quantity
     * @return bool
     */

    function shf_add_to_cart_validation($passed, $product_id, $qty){


        if ( isset( $_POST['_message_front'] ) && sanitize_text_field( $_POST['_message_front'] ) == '' ) {
            $product = wc_get_product( $product_id );
            wc_add_notice( sprintf( __( '%s cannot be added to the cart until you enter some text.', 'shf-custom-msg-front-fields' ), $product->get_title() ), 'error' );
            return false;

    }
       return $passed;

    } 
    add_filter( 'woocommerce_add_to_cart_validation', 'shf_add_to_cart_validation', 10, 3 );

     /*
     * Add custom data to the cart item
     * @param array $cart_item
     * @param int $product_id
     * @return array
     */
    function shf_add_cart_item_data( $cart_item, $product_id ){

        if( isset( $_POST['_message_front'] ) ) {
            $cart_item['message_front'] = sanitize_text_field( $_POST['_message_front'] );
        }

        return $cart_item;

    }
    add_filter( 'woocommerce_add_cart_item_data', 'shf_add_cart_item_data', 10, 2 );


    /*
     * Load cart data from session
     * @param array $cart_item
     * @param array $other_data
     * @return array
     */
    function shf_get_cart_item_from_session( $cart_item, $values ) {

        if ( isset( $values['message_front'] ) ){
            $cart_item['message_front'] = $values['message_front'];
        }

        return $cart_item;

    }
    add_filter( 'woocommerce_get_cart_item_from_session', 'shf_get_cart_item_from_session', 20, 2 );


    /*
     * Add meta to order item
     * @param int $item_id
     * @param array $values
     * @return void
     */
    function shf_add_order_item_meta( $item_id, $values ) {

        if ( ! empty( $values['message_front'] ) ) {
            woocommerce_add_order_item_meta( $item_id, 'message_front', $values['message_front'] );           
        }
    }
    add_action( 'woocommerce_add_order_item_meta', 'shf_add_order_item_meta', 10, 2 );


    /*
     * Get item data to display in cart
     * @param array $other_data
     * @param array $cart_item
     * @return array
     */
    function shf_get_item_data( $other_data, $cart_item ) {

        if ( isset( $cart_item['message_front'] ) ){

            $other_data[] = array(
                'name' => __( 'Front ', 'shf-custom-msg-front-fields' ),
                'value' => sanitize_text_field( $cart_item['message_front'] )
            );

        }

        return $other_data;

    }
    add_filter( 'woocommerce_get_item_data', 'shf_get_item_data', 10, 2 );


    /*
     * Show custom field in order overview
     * @param array $cart_item
     * @param array $order_item
     * @return array
     */
    function shf_order_item_product( $cart_item, $order_item ){

        if( isset( $order_item['message_front'] ) ){
            $cart_item_meta['message_front'] = $order_item['message_front'];
        }

        return $cart_item;

    }
    add_filter( 'woocommerce_order_item_product', 'shf_order_item_product', 10, 2 );


    /* 
     * Add the field to order emails 
     * @param array $keys 
     * @return array 
     */ 
    function shf_email_order_meta_fields( $fields ) { 
        $fields['custom_field'] = __( 'Front ', 'shf-custom-msg-front-fields' ); 
        return $fields; 
    } 
    add_filter('woocommerce_email_order_meta_fields', 'shf_email_order_meta_fields');

I am showing products in table rows. Everything works just fine, the custom fields get posted to cart or show error wc_print_notices(); if not filled up. The problem occurs when I try to use AJAX submission with it. AJAX submits the product, quantity and even variations but it doesn't post the custom field and if I use AJAX then it'll not show error if the field is not filled up, it bypasses the validation and submits the product anyway.

I am out of league here.

Product HTML

        <div class="inn_page">
       <table id="wh_table" class="table table-hover" width="100%" cellspacing="0">
          <thead>
             <tr>
                <th></th>
                <th>PRODUCT</th>
                <th>Message Box</th>
                <th>PRICE</th>
                <th>Quantity</th>
                <th></th>
             </tr>
          </thead>
          <tbody>
             <?php
                $args = array( 
                'post_type' => array('product', 'product_variation'), 
                'post_status' => array('publish', 'pending', 'draft', 'auto-draft', 'future', 'private', 'inherit'),
                'posts_per_page' => -1,
                'product_cat' => '', 
                'post__in' => array( 451, 481, 478, 589 ),
                'orderby' => 'post__in',
                //'order'     => 'DESC',
                'paged'   => get_query_var( 'paged' ) ? get_query_var( 'paged' ) : 1 );
                $wp_query = new WP_Query( $args );
                while ( $wp_query->have_posts() ) : $wp_query->the_post(); 
                global $product; 
                ?>
             <tr class="product-<?php echo esc_attr( $product->id ); ?> variations_form" data-role="product">
                <form action="<?php echo esc_url( $product->add_to_cart_url() ); ?>" class="cart" method="post" enctype='multipart/form-data'>
                   <a href="<?php echo get_permalink( $wp_query->post->ID ) ?>" title="<?php echo esc_attr($wp_query->post->post_title ? $wp_query->post->post_title : $wp_query->post->ID); ?>">
                      <td class="image">
                         <?php woocommerce_show_product_sale_flash( $post, $product ); ?>
                         <?php if (has_post_thumbnail( $wp_query->post->ID )) echo get_the_post_thumbnail($wp_query->post->ID, 'wh_catalog'); else echo '<img src="'.woocommerce_placeholder_img_src().'" alt="Placeholder" width="150px" height="150px" />'; ?>
                      </td>
                      <td class="title">
                         <h3><?php the_title(); ?></h3>
                         <?php if ( ($product->get_id() == 178) || ($product->get_id() == 589) ) { ?>
                         <b>Sterling Silver</b>
                         <?php } ?>                     
                      </td>
                      <td class="note">
                         <?php wholesale_message_front_note(); ?>                           
                      </td>
                      <td class="wh-price">
                         <span><?php echo $product->get_price_html() ?></span>                          
                      </td>
                   </a>
                   <td class="quantity-field">
                      <?php woocommerce_quantity_input(); ?>
                   </td>
                   <td class="button">
                      <input type="hidden" name="add-to-cart" value="<?php echo esc_attr( $product->id ); ?>" />
                      <input type="hidden" name="product_id" value="<?php echo esc_attr( $product->id ); ?>" id="product_id" />
                      <input value="1" id="product_quantity" type="hidden">
                      <button type="submit" class="single_add_to_cart_button btn btn-primary button alt ajax_add_to_cart add_to_cart_button product_type_simple"><span class="glyphicon glyphicon-tag"></span> ADD TO CART</button>
                   </td>
                </form>
             </tr>
             <?php endwhile; ?>
          </tbody>
       </table>
       <!--/.products-->
       <?php wp_reset_query(); ?>               
    </div>

PHP for the AJAX

  function ajax_add_to_cart_script() {
      wp_enqueue_script( 'add-to-cart_ajax', get_template_directory_uri().'/js/add_to_cart_test.js', array('jquery'), '', true );
}
add_action( 'wp_enqueue_scripts', 'ajax_add_to_cart_script',99 );

add_action( 'wp_ajax_woocommerce_add_to_cart_sh', 'woocommerce_add_to_cart_wholesale_sh_callback' );
add_action( 'wp_ajax_nopriv_woocommerce_add_to_cart_sh', 'woocommerce_add_to_cart_sh_callback' );

function woocommerce_add_to_cart_sh_callback() {

    ob_start();

    $product_id = apply_filters( 'woocommerce_add_to_cart_product_id', absint( $_POST['product_id'] ) );
    $quantity = empty( $_POST['quantity'] ) ? 1 : apply_filters( 'woocommerce_stock_amount', $_POST['quantity'] );
    $variation_id = $_POST['variation_id'];
    $variation  = $_POST['variation'];
    $message_front = $_POST['_message_front'];

    $passed_validation = apply_filters( 'woocommerce_add_to_cart_validation', true, $product_id, $quantity, $message_front );

    if ( $passed_validation && WC()->cart->add_to_cart( $product_id, $quantity, $variation_id, $variation, $message_front ) ) {
        do_action( 'woocommerce_ajax_added_to_cart', $product_id );
        if ( get_option( 'woocommerce_cart_redirect_after_add' ) == 'yes' ) {
            wc_add_to_cart_message( $product_id );
        }

        // Return fragments
        WC_AJAX::get_refreshed_fragments();
    } else {
        $this->json_headers();

        // If there was an error adding to the cart, redirect to the product page to show any errors
        $data = array(
            'error' => true,
            'product_url' => apply_filters( 'woocommerce_cart_redirect_after_error', get_permalink( $product_id ), $product_id )
            );
        echo json_encode( $data );
    }
    die();
}  

JS for the AJAX

    jQuery( function( $ ) {

        // wc_add_to_cart_params is required to continue, ensure the object exists
        if ( typeof wc_add_to_cart_params === 'undefined' )
            return false;

        // Ajax add to cart
        $( document ).on( 'click', '.variations_form .single_add_to_cart_button', function(e) {

            e.preventDefault();

            $variation_form = $( this ).closest( '.variations_form' );
            var var_id = $variation_form.find( 'input[name=variation_id]' ).val();

            var product_id = $variation_form.find( 'input[name=product_id]' ).val();
            var quantity = $variation_form.find( 'input[name=quantity]' ).val();

            var message_front = $variation_form.find( 'input[name=_message_front]' ).val();


            //attributes = [];
            $( '.ajaxerrors' ).remove();
            var item = {},
                check = true;

                variations = $variation_form.find( 'select[name^=attribute]' );

                if ( !variations.length) {
                    variations = $variation_form.find( '[name^=attribute]:checked' );
                }

                /* Backup Code for getting input variable */
                if ( !variations.length) {
                    variations = $variation_form.find( 'input[name^=attribute]' );
                }

            variations.each( function() {

                var $this = $( this ),
                    attributeName = $this.attr( 'name' ),
                    attributevalue = $this.val(),
                    index,
                    attributeTaxName;

                $this.removeClass( 'error' );

                if ( attributevalue.length === 0 ) {
                    index = attributeName.lastIndexOf( '_' );
                    attributeTaxName = attributeName.substring( index + 1 );

                    $this
                        //.css( 'border', '1px solid red' )
                        .addClass( 'required error' )
                        //.addClass( 'barizi-class' )
                        .before( '<div class="ajaxerrors"><p>Please select ' + attributeTaxName + '</p></div>' )

                    check = false;
                } else {
                    item[attributeName] = attributevalue;
                }

                // Easy to add some specific code for select but doesn't seem to be needed
                // if ( $this.is( 'select' ) ) {
                // } else {
                // }

            } );

            if ( !check ) {
                return false;
            }

            //item = JSON.stringify(item);
            //alert(item);
            //return false;

            // AJAX add to cart request

            var $thisbutton = $( this );

            if ( $thisbutton.is( '.variations_form .single_add_to_cart_button' ) ) {

                $thisbutton.removeClass( 'added' );
                $thisbutton.addClass( 'loading' );

                var data = {
                    action: 'woocommerce_add_to_cart_sh',
                    product_id: product_id,
                    quantity: quantity,
                    variation_id: var_id,
                    variation: item,
                    message_front: message_front                        
                };

                // Trigger event
                $( 'body' ).trigger( 'adding_to_cart', [ $thisbutton, data ] );

                // Ajax action
                $.post( wc_add_to_cart_params.ajax_url, data, function( response ) {

                    if ( ! response )
                        return;

                    var this_page = window.location.toString();

                    this_page = this_page.replace( 'add-to-cart', 'added-to-cart' );

                    if ( response.error && response.product_url ) {
                        window.location = response.product_url;
                        return;
                    }

                    if ( wc_add_to_cart_params.cart_redirect_after_add === 'yes' ) {

                        window.location = wc_add_to_cart_params.cart_url;
                        return;

                    } else {

                        $thisbutton.removeClass( 'loading' );

                        var fragments = response.fragments;
                        var cart_hash = response.cart_hash;

                        // Block fragments class
                        if ( fragments ) {
                            $.each( fragments, function( key ) {
                                $( key ).addClass( 'updating' );
                            });
                        }

                        // Block widgets and fragments
                        $( '.shop_table.cart, .updating, .cart_totals' ).fadeTo( '400', '0.6' ).block({
                            message: null,
                            overlayCSS: {
                                opacity: 0.6
                            }
                        });

                        // Changes button classes
                        $thisbutton.addClass( 'added' );

                        // View cart text
                        if ( ! wc_add_to_cart_params.is_cart && $thisbutton.parent().find( '.added_to_cart' ).size() === 0 ) {
                            $thisbutton.after( ' <a href="' + wc_add_to_cart_params.cart_url + '" class="added_to_cart wc-forward" title="' +
                                wc_add_to_cart_params.i18n_view_cart + '">' + wc_add_to_cart_params.i18n_view_cart + '</a>' );
                        }

                        // Replace fragments
                        if ( fragments ) {
                            $.each( fragments, function( key, value ) {
                                $( key ).replaceWith( value );
                            });
                        }

                        // Unblock
                        $( '.widget_shopping_cart, .updating' ).stop( true ).css( 'opacity', '1' ).unblock();

                        // Cart page elements
                        $( '.shop_table.cart' ).load( this_page + ' .shop_table.cart:eq(0) > *', function() {

                            $( '.shop_table.cart' ).stop( true ).css( 'opacity', '1' ).unblock();

                            $( document.body ).trigger( 'cart_page_refreshed' );
                        });

                        $( '.cart_totals' ).load( this_page + ' .cart_totals:eq(0) > *', function() {
                            $( '.cart_totals' ).stop( true ).css( 'opacity', '1' ).unblock();
                        });

                        // Trigger event so themes can refresh other areas
                        $( document.body ).trigger( 'added_to_cart', [ fragments, cart_hash, $thisbutton ] );
                    }
                });
    console.log (error);
                return false;

            } else {
                return true;
            }

        });

    });

$message_front = $_POST['_message_front']; doesn't have anything stored. What am I doing wrong? I am bit lost here, please help me out.

回答1:

A simple underscore made my nights sleepless for the past few days. message_front should be _message_front