Bedingte benutzerdefinierte Checkout-Felder basierend auf der Produktkategorie in Woocommerce

Lesezeit: 17 Minuten

Benutzer-Avatar
James

Ich verwende woocommerce für eine Website für eine gemeinnützige Organisation, die Tickets für Kurse und Tickets für Veranstaltungen verkauft. Wenn sich jemand für einen Kurs anmeldet, muss er seine Notfallkontaktinformationen angeben und einer Haftungsfreistellung zustimmen. Wenn sie ein Ticket für eine Veranstaltung kaufen, benötigt die gemeinnützige Organisation weder die Notfallkontaktinformationen noch die Haftungsfreistellung. Sie möchten also, dass diese Felder nur unter der Bedingung an der Woocommerce-Kasse erscheinen, dass die Person mit einem Ticket für eine Klasse auscheckt. Sinn ergeben?

Ich habe vor ein paar Monaten herausgefunden, wie man die benutzerdefinierten Felder und die benutzerdefinierten Haftungsfreigaben hinzufügt, als sie die Klassen zum ersten Mal zur Website hinzufügten. Ich habe in WooCommerce eine “Klassen”-Produktkategorie und eine Funktion zum Testen von Produkten im Warenkorb erstellt, die sich in dieser Kategorie befinden, damit ich die Felder bedingt anzeigen kann.

Alle diese Funktionen befinden sich in meiner Datei functions.php und ich führe gerade die bedingte Anweisung aus, um in jeder der Funktionen nach der Kategorie “Klasse” zu suchen. Ich brauche Hilfe, um zu lernen, wie man einmal nach der Kategorie „Klasse“ sucht, dann die Funktionen ausführt, die die Felder anzeigen, die Felder validieren, die Daten zur Datenbank hinzufügen und die neuen Bestell-E-Mails generieren. Sinn ergeben?

Hier ist, was ich derzeit habe:

// 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;

}

Wie Sie wahrscheinlich sehen können, habe ich dies aus verschiedenen Quellen im Internet zusammengestellt und mir ist klar, dass es ein bisschen chaotisch ist. Aktuell die bedingte Aussage:

// 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 ) {

Wird für jede Funktion wiederholt. Ich weiß, dass dies nicht effizient ist, aber ich bin mir nicht sicher, wie ich es beheben kann. Was ich gerne machen möchte ist folgendes:

  1. Testen Sie auf Produkte, die in der Kategorie “Klasse” sind
  2. Wenn „Klasse“ dann laufen alle Funktionen zur Anzeige und Bearbeitung von Notfallkontaktfeldern und Fotofreigabe und Haftungsfreigabefeldern
  3. Zeigen Sie die Vereinbarung “Mailingliste beitreten” an, unabhängig davon, ob sich eine “Klasse” im Warenkorb befindet oder nicht, und verarbeiten Sie dieses Feld, egal was passiert.

Ich habe versucht, alles in eine andere Funktion zu packen, aber das hat den Code kaputt gemacht. Vielleicht wäre es am besten, dies in ein Plugin zu verschieben?

Vielen Dank für Ideen und Hilfe, die Sie geben können.

Benutzer-Avatar
LoicTheAztec

Erstens ist der bedingte Funktionscode, den Sie verwenden, wirklich alt, veraltet und wird nicht funktionieren wenn Warenkorbartikel Produktvariationen sind (also für variable Produkte). Hier unten ist die kompakte und funktionierende bedingte Funktion…
Es kann mit jeder Produktkategorie-Begriffs-ID, jedem Slug, Namen oder einem Array von Werten arbeiten:

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;
}

Jetzt hat der Rest Ihres Codes viele Fehler oder kleine Fehler.

Es verwendet auch veraltete oder veraltete Hooks wie:

  • woocommerce_checkout_update_order_meta durch einen viel angebrachten Haken ersetzt.
  • woocommerce_email_order_meta_keys ist seit langem veraltet.

Sie können auch Code in denselben Hook-Funktionen zusammenführen.

Sie brauchen die bedingte Funktion nicht überall. Es wird nur für die bedingte Anzeige von Checkout-Feldern benötigt.

Hier ist Ihr überarbeiteter Code (für woocommerce Version 3 und höher):

// 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>';
}

Der Code wird in die function.php-Datei Ihres aktiven untergeordneten Designs (oder aktiven Designs) eingefügt. Getestet und funktioniert.

Fazit: Wenn ein Code in der function.php-Datei nicht funktioniert, wird er in einem Plugin nicht besser funktionieren. Aber wenn Sie möchten, können Sie es in einem Plugin hinzufügen, wenn Sie es vorziehen.

  • Vielen Dank für Ihre schnelle und gründliche Antwort und danke, dass Sie sich die Zeit genommen haben, den von mir geposteten Code zu überarbeiten. Ich hatte nur auf ein paar Hinweise gehofft! Ich denke, ich hätte Stackoverflow beitreten und vor langer Zeit um Hilfe bitten sollen, ich habe das Gefühl, es hätte mir viele Stunden erspart, meinen Kopf gegen die Wand zu schlagen. Ich freue mich darauf, den Code diese Woche zu vergleichen, damit ich aus Ihren Änderungen lernen kann.

    – James

    11. Juni 2018 um 0:08 Uhr

  • Was ist der beste Weg, um die benutzerdefinierten Informationen an die E-Mail-Vorlage für neue Bestellungen zu übergeben? Ich habe eine benutzerdefinierte Vorlage für diese E-Mail erstellt, aber wenn möglich, würde ich es lieber über die function.php tun ….

    – James

    15. Juni 2018 um 15:57 Uhr

1244960cookie-checkBedingte benutzerdefinierte Checkout-Felder basierend auf der Produktkategorie in Woocommerce

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy