基于Woocommerce中产品类别的条件自定义结帐字段 - php

我将woocommerce用于非营利性网站,该网站出售课程门票和活动门票。当某人报名参加课程时,需要列出其紧急联系信息并同意免除责任。当他们购买活动的门票时,非营利组织不需要紧急联系信息或责任解除。所以...他们只希望这些字段出现在woocommerce结帐中,但前提是该人正在使用课程票进行结帐。合理?

我想出了如何添加自定义字段,几个月前,当他们首次将类添加到网站时,他们发布了自定义责任。我在woocommerce中创建了一个“类”产品类别,并创建了一个功能来测试购物车中该类别中的任何产品,因此我可以有条件地显示这些字段。

所有这些功能都在我的functions.php文件中,现在我正在运行条件语句来检查每个功能中的“类”类别。我需要帮助来学习如何一次检查“类”类别,然后运行显示字段,验证字段,将数据添加到数据库并生成新订单电子邮件的功能。合理?

这是我目前所拥有的:

// Add fields for Emergency Contact & Medical Information to the checkout page
add_action('woocommerce_after_order_notes', 'customise_checkout_field');

function customise_checkout_field($checkout)
{

    // Check to see if there is a class in the cart
    // function is at the end
    $class_in_cart = is_conditional_product_in_cart( 'class' );

    // There is a class in the cart so show additional fields
    if ( $class_in_cart === true ) {

    echo '<div id="customise_checkout_field"><h3>' . __('Emergency Contact & Medical Information') . '</h3>';
    woocommerce_form_field('emergency_contact', array(
        'type' => 'text',
        'class' => array(
            'emergency-contact form-row-wide'
        ) ,
        'label' => __('Emergency Contact') ,
        'placeholder' => __('Please enter first & last name') ,
        'required' => true,
    ) , $checkout->get_value('emergency_contact'));
    woocommerce_form_field('emergency_contact_relationship', array(
        'type' => 'text',
        'class' => array(
            'emergency-contact-relationship form-row-wide'
        ) ,
        'label' => __('What is your relationship with this person?') ,
        'placeholder' => __('Example: Mother') ,
        'required' => true,
    ) , $checkout->get_value('emergency_contact_relationship'));
    woocommerce_form_field('emergency_contact_phone', array(
        'type' => 'text',
        'class' => array(
            'emergency-contact-phone form-row-wide'
        ) ,
        'label' => __('What is their phone number?') ,
        'placeholder' => __('(555) 555-5555') ,
        'required' => true,
    ) , $checkout->get_value('emergency_contact_phone'));
    woocommerce_form_field('medical_medicine', array(
        'type' => 'textarea',
        'class' => array(
            'medical-medicine form-row-wide'
        ) ,
        'label' => __('Do you have any medical conditions and are you taking any medications we need to be aware of?') ,
        'placeholder' => __('If not please write in "none"') ,
        'required' => true,
    ) , $checkout->get_value('medical_medicine'));
    echo '</div>';
    }
}

// Process emergency contact fields

add_action('woocommerce_checkout_process', 'custom_checkout_fields_process');

function custom_checkout_fields_process() {
    // Check to see if there is a class in the cart
    $class_in_cart = is_conditional_product_in_cart( 'class' );

    // There is a class in the cart so show additional fields
    if ( $class_in_cart === true ) {

        // if the field is set, if not then show an error message.
        if (!$_POST['emergency_contact']) wc_add_notice(__('Please list an emergency contact.') , 'error');
        if (!$_POST['emergency_contact_relationship']) wc_add_notice(__('Please indicate your relationship with your emergency contact.') , 'error');
        if (!$_POST['emergency_contact_phone']) wc_add_notice(__('Please list a phone number for your emergency contact.') , 'error');
        if (!$_POST['medical_medicine']) wc_add_notice(__('Please list any medications or write in "none".') , 'error');
    }
}

// Add emergency contact information to the database

add_action('woocommerce_checkout_update_order_meta', 'custom_checkout_fields_update_order_meta');

function custom_checkout_fields_update_order_meta($order_id) {
    // Check to see if there is a class in the cart
    $class_in_cart = is_conditional_product_in_cart( 'class' );

    // There is a class in the cart so show additional fields
    if ( $class_in_cart === true ) {
        if (!empty($_POST['emergency_contact'])) {
            update_post_meta($order_id, 'emergency_contact', sanitize_text_field($_POST['emergency_contact']));
        }
        if (!empty($_POST['emergency_contact_relationship'])) {
            update_post_meta($order_id, 'emergency_contact_relationship', sanitize_text_field($_POST['emergency_contact_relationship']));
        }
        if (!empty($_POST['emergency_contact_phone'])) {
            update_post_meta($order_id, 'emergency_contact_phone', sanitize_text_field($_POST['emergency_contact_phone']));
        }
        if (!empty($_POST['medical_medicine'])) {
            update_post_meta($order_id, 'medical_medicine', sanitize_text_field($_POST['medical_medicine']));
        }
    }
}

// Add the emergency contact fields to order email

add_filter( 'woocommerce_email_order_meta_keys', 'my_custom_checkout_field_order_meta_keys' );
function my_custom_checkout_field_order_meta_keys( $keys ) {
    // Check to see if there is a class in the cart
    $class_in_cart = is_conditional_product_in_cart( 'class' );

    // There is a class in the cart so show additional fields
    if ( $class_in_cart === true ) {
        echo '<h2>Emergency Contact & Medical Information:</h2>';
        $keys['Emergency Contact'] = 'emergency_contact';
        $keys['Emergency Contact Relationship'] = 'emergency_contact_relationship';
        $keys['Emergency Contact Phone'] = 'emergency_contact_phone';
        $keys['Medical Conditions & Medications'] = 'medical_medicine';
        return $keys;
    } // end class in cart condition
}

/*-----------------------------------------------------------------------------------------------------------------------------------------------*/

// Add custom checkboxes to woocommerce checkout page for Photo Release, Mailing List & Release of Liability
// add_action( 'woocommerce_after_order_notes', 'custom_checkout_fields' );
add_action( 'woocommerce_review_order_before_submit', 'custom_checkout_fields' );
function custom_checkout_fields() {
    echo '<div id="custom_checkout_fields">
    <h3>Mailing Lists</h3>
    <p>Mailing List boilerplate';

    woocommerce_form_field( 'mailing_consent', array(
        'type'      => 'checkbox',
        'class'     => array('input-checkbox'),
        'label'     => __('Please add me to Nonprofit\'s electronic and paper mailing lists.'),
        'required'  => false,
        'clear'     => true,
        'default'   => 1 //This will pre-select the checkbox
    ),  WC()->checkout->get_value( 'mailing_consent' ) );

    // Check to see if there is a class in the cart
    $class_in_cart = is_conditional_product_in_cart( 'class' );

    // There is a class in the cart so show additional fields
    if ( $class_in_cart === true ) {

        echo '<h3>Photo Release</h3>
        <p>Photo Release Boilerplate</p>';

        woocommerce_form_field( 'photo_consent', array(
            'type'      => 'checkbox',
            'class'     => array('input-checkbox'),
            'label'     => __('I agree to the Photo Release as outlined above.'),
            'required'  => false,
            'clear'     => true,
            'default'   => 1 //This will pre-select the checkbox
        ),  WC()->checkout->get_value( 'photo_consent' ) );

        echo '<h3>Release of Liability</h3>
        <p>Release of Liability Boilerplate</p>';

        woocommerce_form_field( 'liability_release', array(
            'type'      => 'checkbox',
            'class'     => array('input-checkbox'),
            'label'     => __('I agree to the Photo Release as outlined above.'),
            'required'  => true,
            'clear'     => true,
            'default'   => 1 //This will pre-select the checkbox
        ),  WC()->checkout->get_value( 'liability_release' ) );

    } // end class in cart condition

    echo '</div>';
}

// Show notice if customer doesn't check the Release of Liability checkbox
add_action( 'woocommerce_checkout_process', 'liability_release_not_given' );

function liability_release_not_given() {
    // Check to see if there is a class in the cart
    $class_in_cart = is_conditional_product_in_cart( 'class' );

    // There is a class in the cart so show additional fields
    if ( $class_in_cart === true ) {
        if ( ! (int) isset( $_POST['liability_release'] ) ) {
            wc_add_notice( __( 'You must agree to the Release of Liability to register for this class.  Please contact us with any questions.' ), 'error' );
        }
    } // end class in cart condition
}

// Save the custom checkout field in the order meta, when checkbox has been checked
add_action( 'woocommerce_checkout_update_order_meta', 'custom_checkout_field_update_order_meta', 10, 1 );
function custom_checkout_field_update_order_meta( $order_id ) {

    if ( ! empty( $_POST['mailing_consent'] ) )
        update_post_meta( $order_id, 'mailing_consent', $_POST['mailing_consent'] );

    if ( ! empty( $_POST['photo_consent'] ) )
        update_post_meta( $order_id, 'photo_consent', $_POST['photo_consent'] );

    if ( ! empty( $_POST['liability_release'] ) )
        update_post_meta( $order_id, 'liability_release', $_POST['liability_release'] );
}

/*-----------------------------------------------------------------------------------------------------------------------------------------------*/

// Display custom field results on the order edit page (backend)
// for various liability fields

add_action( 'woocommerce_admin_order_data_after_billing_address', 'display_custom_field_on_order_edit_pages', 10, 1 );
function display_custom_field_on_order_edit_pages( $order ){

    $mailing_consent = get_post_meta( $order->get_id(), 'mailing_consent', true );
    if( $mailing_consent == 1 )
        echo '<p>' . $order->billing_first_name . ' ' . $order->billing_last_name . ' agreed to the be added to Nonprofit\'s mailing lists.</p>';

    $photo_consent = get_post_meta( $order->get_id(), 'photo_consent', true );
    if( $photo_consent == 1 )
        echo '<p>' . $order->billing_first_name . ' ' . $order->billing_last_name . ' agreed to the Photo Release.</p>';

    $liability_release = get_post_meta( $order->get_id(), 'liability_release', true );
    if( $liability_release == 1 )
        echo '<p>' . $order->billing_first_name . ' ' . $order->billing_last_name . ' agreed to the Release of Liability.</p>';
}


/**
 * Check if Class is In cart
 *
 * https://wordimpress.com/create-conditional-checkout-fields-woocommerce/
 * https://businessbloomer.com/woocommerce-check-product-category-cart/
 *
 * @param $product_id
 *
 * @return bool
 */
function is_conditional_product_in_cart( $category_name ) {
    //Check to see if user has a class in their cart
    global $woocommerce;

    //flag no class in cart
    $class_in_cart = false;

    foreach ( $woocommerce->cart->get_cart() as $cart_item_key => $values ) {
        $_product = $values['data'];

    //  if ( $_product->cat === $category_id ) {
        //  //class is in cart!
            //$class_in_cart = true;

        if (has_term ( $category_name, 'product_cat', $_product->get_id() ) ) {
            //class is in cart!
            $class_in_cart = true;
        }
    }

    return $class_in_cart;

}

您可能会说,我是从网络上的各种来源中整理出来的,但我意识到这有点混乱。当前条件语句:

// Check to see if there is a class in the cart
$class_in_cart = is_conditional_product_in_cart( 'class' );

// There is a class in the cart so show additional fields
if ( $class_in_cart === true ) {

为每个功能重复。我知道这不是很有效,但是我不确定如何解决。我想做的是这样的:

测试“类别”类别中的产品
如果为“ class”,则运行所有功能以显示和处理紧急联系人字段以及照片发布和责任发布字段
显示“加入邮件列表”协议,无论购物车中是否有“类别”,无论如何都要处理该字段。

我尝试将所有内容包装在另一个函数中,但这破坏了代码。也许最好将其移动到插件中?

感谢您提供任何想法和帮助。

参考方案

首先,您使用的条件功能代码确实很旧,过时,并且当购物车商品是产品变体时(因此对于可变产品)将无法使用。以下是紧凑而有效的条件函数…它可以与任何产品类别术语ID,段,名称或值数组一起使用:

function is_product_cat_in_cart( $categories ) {
    foreach ( WC()->cart->get_cart() as $cart_item ) {
        if (has_term ( $categories, 'product_cat', $cart_item['product_id'] ) )
            return true;
    }
    return false;
}

现在,您的其余代码中有很多错误或几乎没有错误。

它还使用过时或过时的钩子,例如:

woocommerce_checkout_update_order_meta替换为一个非常合适的钩子。
woocommerce_email_order_meta_keys从很多时候开始就被弃用。

您也可以在相同的挂钩函数中将一些代码合并在一起。

您不需要到处都有条件函数。结帐字段条件显示只需要它。

这是您重新访问的代码(适用于woocommerce版本3及更高版本):

// Add fields for Emergency Contact & Medical Information to the checkout page
add_action('woocommerce_after_order_notes', 'customise_checkout_field', 20, 1 );
function customise_checkout_field( $checkout ){
    $domain = 'woocommerce';

    // There is a class in the cart so show additional fields
    if ( is_product_cat_in_cart( 'class' ) ):

    echo '<div id="customise_checkout_field">
    <h3>' . __( 'Emergency Contact & Medical Information', $domain ) . '</h3>';

    woocommerce_form_field( 'emergency_contact', array(
        'type'          => 'text',
        'class'         => array( 'emergency-contact form-row-wide' ),
        'label'         => __( 'Emergency Contact', $domain ) ,
        'placeholder'   => __( 'Please enter first & last name', $domain ),
        'required'      => true,
    ), $checkout->get_value('emergency_contact') );

    woocommerce_form_field( 'emergency_contact_relationship', array(
        'type'          => 'text',
        'class'         => array( 'emergency-contact-relationship form-row-wide' ),
        'label'         => __( 'What is your relationship with this person?', $domain ),
        'placeholder'   => __( 'Example: Mother', $domain ) ,
        'required'      => true,
    ), $checkout->get_value('emergency_contact_relationship') );

    woocommerce_form_field( 'emergency_contact_phone', array(
        'type'          => 'text',
        'class'         => array( 'emergency-contact-phone form-row-wide' ),
        'label'         => __( 'What is their phone number?', $domain ),
        'placeholder'   => __( '(555) 555-5555', $domain ),
        'required'      => true,
    ), $checkout->get_value('emergency_contact_phone') );

    woocommerce_form_field( 'medical_medicine', array(
        'type'          => 'textarea',
        'class'         => array( 'medical-medicine form-row-wide' ) ,
        'label'         => __( 'Do you have any medical conditions and are you taking any medications we need to be aware of?', $domain ),
        'placeholder'   => __( 'If not please write in "none"', $domain ),
        'required'      => true,
    ) , $checkout->get_value('medical_medicine') );
    echo '</div>';

    endif;
}

// Add custom checkboxes to woocommerce checkout page for Photo Release, Mailing List & Release of Liability
add_action( 'woocommerce_review_order_before_submit', 'custom_checkout_fields' );
function custom_checkout_fields() {
    $checkout = WC()->checkout;
    $domain   = 'woocommerce';

    echo '<div id="custom_checkout_fields">
    <h3>'.__( 'Mailing Lists', $domain ).'</h3>
    <p>'.__( 'Mailing List boilerplate', $domain ).'</p>';

    woocommerce_form_field( 'mailing_consent', array(
        'type'      => 'checkbox',
        'class'     => array('input-checkbox'),
        'label'     => __( 'Please add me to Nonprofit\'s electronic and paper mailing lists.', $domain ),
        'required'  => false,
        'clear'     => true,
        'default'   => 1 //This will pre-select the checkbox
    ),  $checkout->get_value( 'mailing_consent' ) );

    // There is a class in the cart so show additional fields
    if ( is_product_cat_in_cart( 'class' ) ):

    echo '<h3>'.__( 'Photo Release', $domain ).'</h3>
    <p>'.__( 'Photo Release Boilerplate', $domain ).'</p>';

    woocommerce_form_field( 'photo_consent', array(
        'type'      => 'checkbox',
        'class'     => array('input-checkbox'),
        'label'     => __( 'I agree to the Photo Release as outlined above.', $domain ),
        'required'  => false,
        'clear'     => true,
        'default'   => 1 //This will pre-select the checkbox
    ),  $checkout->get_value( 'photo_consent' ) );

    echo '<h3>'.__( 'Release of Liability', $domain ).'</h3>
    <p>'.__( 'Release of Liability Boilerplate', $domain ).'</p>';

    woocommerce_form_field( 'liability_release', array(
        'type'      => 'checkbox',
        'class'     => array('input-checkbox'),
        'label'     => __( 'I agree to the Photo Release as outlined above.', $domain ),
        'required'  => true,
        'clear'     => true,
        'default'   => 1 //This will pre-select the checkbox
    ),  $checkout->get_value( 'liability_release' ) );

    endif;

    echo '</div>';
}

// Custom checkout fields validation
add_action('woocommerce_checkout_process', 'custom_checkout_fields_process');
function custom_checkout_fields_process() {
    $domain = 'woocommerce';

    if ( isset($_POST['emergency_contact']) && empty($_POST['emergency_contact']) )
        wc_add_notice( __( 'Please list an emergency contact.', $domain ) , 'error' );

    if ( isset($_POST['emergency_contact_relationship']) && empty($_POST['emergency_contact']) )
        wc_add_notice( __( 'Please indicate your relationship with your emergency contact.', $domain ), 'error' );

    if ( isset($_POST['emergency_contact_phone']) && empty($_POST['emergency_contact']) )
        wc_add_notice( __( 'Please list a phone number for your emergency contact.', $domain ), 'error' );

    if ( isset($_POST['medical_medicine']) && empty($_POST['emergency_contact']) )
        wc_add_notice( __( 'Please list any medications or write in "none".', $domain ), 'error' );

    // Other checkout fields
    if ( ! isset( $_POST['liability_release'] ) && ! $_POST['liability_release'] && isset($_POST['photo_consent']) )
        wc_add_notice( __( 'You must agree to the Release of Liability to register for this class.  Please contact us with any questions.', $domain ), 'error' );
}

// Save custom checkout fields in the order meta data
add_action( 'woocommerce_checkout_create_order', 'custom_checkout_fields_in_order_meta_data', 20, 2 );
function custom_checkout_fields_in_order_meta_data( $order, $data ) {

    if ( isset($_POST['emergency_contact']) && ! empty($_POST['emergency_contact']) )
        $order->update_meta_data( 'emergency_contact', sanitize_text_field($_POST['emergency_contact']) );

    if ( isset($_POST['emergency_contact_relationship']) && ! empty($_POST['emergency_contact_relationship']) )
        $order->update_meta_data( 'emergency_contact_relationship', sanitize_text_field($_POST['emergency_contact_relationship']) );

    if ( isset($_POST['emergency_contact_phone']) && ! empty($_POST['emergency_contact_phone']) )
        $order->update_meta_data( 'emergency_contact_phone', sanitize_text_field($_POST['emergency_contact_phone']) );

    if ( isset($_POST['medical_medicine']) && ! empty($_POST['medical_medicine']) )
        $order->update_meta_data( 'medical_medicine', sanitize_text_field($_POST['medical_medicine']) );

    if ( isset($_POST['mailing_consent']) && ! empty($_POST['mailing_consent']) )
        $order->update_meta_data( 'mailing_consent', '1' );

    if ( isset( $_POST['photo_consent']) && ! empty($_POST['photo_consent']) )
        $order->update_meta_data( 'photo_consent', '1' );

    if ( isset( $_POST['liability_release']) && ! empty($_POST['liability_release']) )
        $order->update_meta_data( 'liability_release', '1' );
}

// Add the emergency contact fields to email notifications
add_filter( 'woocommerce_email_order_meta_fields', 'custom_checkout_field_email_order_meta', 20, 3 );
function custom_checkout_field_email_order_meta( $fields, $sent_to_admin, $order ) {
    $domain = 'woocommerce';

    if( ! $order->get_meta( 'emergency_contact' ) )
        return $fields; // Exit if not set in the order

    echo '<h2>'.__( 'Emergency Contact & Medical Information', $domain ).'</h2>';

    $fields[] = array( 'label' => __( 'Emergency contact', $domain ),
        'value' => $order->get_meta( 'emergency_contact' ) );

    $fields[] = array( 'label' => __( 'Emergency Contact Relationship', $domain ),
        'value' => $order->get_meta( 'emergency_contact_relationship' ) );

    $fields[] = array( 'label' => __( 'Emergency Contact Phone', $domain ),
        'value' => $order->get_meta( 'emergency_contact_phone' ) );

    $fields[] = array( 'label' => __( 'Medical Conditions & Medications', $domain ),
        'value' => $order->get_meta( 'medical_medicine' ) );

    return $fields;
}

// Display some custom checkout fields in Order edit pages
add_action( 'woocommerce_admin_order_data_after_billing_address', 'display_custom_field_on_order_edit_pages', 20, 1 );
function display_custom_field_on_order_edit_pages( $order ){
    $domain = 'woocommerce';

    $billing_name = $order->get_billing_first_name().' '.$order->get_billing_last_name();

    if( $order->get_meta('mailing_consent') )
        echo '<p>' . $billing_name . __( ' agreed to the be added to Nonprofit\'s mailing lists.', $domain ).'</p>';

    if( $order->get_meta('photo_consent') )
        echo '<p>' . $billing_name . __( ' agreed to the Photo Release.', $domain ).'</p>';

    if( $order->get_meta('liability_release') )
        echo '<p>' . $billing_name . __( ' agreed to the Release of Liability.', $domain ).'</p>';
}

代码进入您的活动子主题(或活动主题)的function.php文件中。经过测试和工作。

结论:如果一些代码在function.php文件中不起作用,则在插件中不能更好地工作。但是,如果愿意,可以根据需要将其添加到插件中。

验证IBAN PHP - php

在设计新平台时,我们尝试集成IBAN编号。我们必须确保IBAN已经过验证,并且存储在数据库中的IBAN始终正确。那么验证数字的正确方法是什么? 参考方案 正如我在其他问题中解释的逻辑一样,我尝试自己创建一个函数。根据Wikipedia文章中解释的逻辑,在下面找到合适的功能。国家特定验证。它适合吗http://en.wikipedia.org/wiki/Int…

PHP:对数组排序 - php

请如何排序以下数组Array ( 'ben' => 1.0, 'ken' => 2.0, 'sam' => 1.5 ) 至Array ( 'ken' => 2.0, 'sam' => 1.5, 'ben' =&…

PHP PDO组按列名称查询结果 - php

以下PDO查询返回以下结果:$db = new PDO('....'); $sth = $db->prepare('SELECT ...'); 结果如下: name curso ABC stack CDE stack FGH stack IJK stack LMN overflow OPQ overflow RS…

PHP:不推荐使用password_hash的'salt'选项 - php

我正在使用密码哈希进行注册。我需要手动创建Salt,以下是我使用的代码:$options = [ 'cost' => 11, 'salt' => mcrypt_create_iv(22, MCRYPT_DEV_URANDOM) ]; $password = password_hash( $this->…

PHP-嵌套的foreach循环中的异常行为 - php

一些背景我有2个数组,其中包含以下信息:$x = [ ['name' => 'Fred', 'ykey' => 'A', 'rank' => '1', 'VIP' => '1'…