WooCommerce har två kassor, och ett eget fält görs på två helt olika sätt. I blockkassan registrerar du fältet med woocommerce_register_additional_checkout_field(), och WooCommerce sköter visning, sparande, validering, tacksidan och orderadmin åt dig. I den klassiska kassan lägger du till fältet med filtret woocommerce_checkout_fields och sparar det själv på ordern. Hooks från den ena kassan gör ingenting i den andra.
Exemplet nedan är ett fält för leveransinstruktion, det jag oftast får beställt i B2B-butiker: portkod, var paketet får ställas, vem som tar emot. Koden ligger i ett eget litet plugin. Lägg inte kassakod i temat, eftersom den ska finnas kvar om butiken byter tema.
Gäller blockkassan
Blockkassan har ett eget API för fält. Fältet får ett id i formen namnrymd/namn, en plats (contact, address eller order) och en typ (text, select eller checkbox). Registreringen måste ske på woocommerce_init eller senare, annars ignoreras den med ett fel i felsökningsloggen.
<?php
/**
* Plugin Name: WPU Delivery Instruction (Block Checkout)
* Requires Plugins: woocommerce
*/
defined( 'ABSPATH' ) || exit;
// Gäller blockkassan. Registration must run on woocommerce_init or later.
add_action( 'woocommerce_init', 'wpu_register_delivery_instruction_block_field' );
function wpu_register_delivery_instruction_block_field() {
if ( ! function_exists( 'woocommerce_register_additional_checkout_field' ) ) {
return;
}
woocommerce_register_additional_checkout_field(
array(
'id' => 'wpu/leveransinstruktion',
'label' => 'Leveransinstruktion (portkod, var paketet får lämnas)',
'location' => 'order',
'type' => 'text',
'required' => false,
'attributes' => array( 'maxLength' => '120' ),
// Return a WP_Error to block the order with your own message; true accepts the value.
'validate_callback' => function ( $value ) {
if ( mb_strlen( (string) $value ) > 120 ) {
return new WP_Error( 'wpu_leveransinstruktion_for_lang', 'Leveransinstruktionen får vara högst 120 tecken.' );
}
return true;
},
)
);
}
Mer behöver du inte göra för själva kassan. Fältet visas i kassans avsnitt för orderinformation, värdet sparas på ordern med metanyckeln _wc_other/wpu/leveransinstruktion, det visas på tacksidan och under ordern i Mitt konto, och det dyker upp redigerbart i orderadmin under leveransadressen. Fält med platsen address sparas dessutom på kundens adress och fält med platsen contact under kontouppgifterna.
Vill du ha en rullista byter du typ till select och lägger till options som en lista med value och label. En kryssruta har typen checkbox och sparas som 1 eller tom sträng.
Gäller den klassiska kassan
Den klassiska kassan har inget register. Du lägger till fältet i filtret woocommerce_checkout_fields under sektionen order, där orderanteckningen redan ligger, och sparar värdet själv när ordern skapas. WooCommerce skickar med allt som postats i kassan som $data till woocommerce_checkout_create_order, och validerar required och maxlength åt dig.
<?php
/**
* Plugin Name: WPU Delivery Instruction (Classic Checkout)
* Requires Plugins: woocommerce
*/
defined( 'ABSPATH' ) || exit;
// Gäller den klassiska kassan. Adds the field to the "order" section, next to the order notes.
add_filter( 'woocommerce_checkout_fields', 'wpu_add_delivery_instruction_classic_field' );
function wpu_add_delivery_instruction_classic_field( $fields ) {
$fields['order']['wpu_leveransinstruktion'] = array(
'type' => 'text',
'label' => 'Leveransinstruktion (portkod, var paketet får lämnas)',
'required' => false,
'maxlength' => 120,
'class' => array( 'form-row-wide' ),
'priority' => 5, // Order notes have priority 10, so this renders above them.
);
return $fields;
}
// Gäller den klassiska kassan. $data holds every posted checkout field, already sanitized by WooCommerce.
add_action( 'woocommerce_checkout_create_order', 'wpu_save_delivery_instruction_classic', 10, 2 );
function wpu_save_delivery_instruction_classic( $order, $data ) {
if ( ! empty( $data['wpu_leveransinstruktion'] ) ) {
$order->update_meta_data( '_wpu_leveransinstruktion', sanitize_text_field( $data['wpu_leveransinstruktion'] ) );
}
}
// Gäller den klassiska kassan. The block checkout shows its fields in admin by itself; this one needs a line.
add_action( 'woocommerce_admin_order_data_after_shipping_address', 'wpu_show_delivery_instruction_in_admin' );
function wpu_show_delivery_instruction_in_admin( $order ) {
$value = $order->get_meta( '_wpu_leveransinstruktion' );
if ( '' !== $value ) {
echo '<p><strong>Leveransinstruktion:</strong> ' . esc_html( $value ) . '</p>';
}
}
Metanyckeln börjar med understreck så att den inte visas som ett vanligt anpassat fält. Vill du att kunden ska se värdet på tacksidan lägger du till en liknande utskrift på woocommerce_order_details_after_customer_details.
Visa fältet i ordermejlen, oavsett kassa
Blockkassan visar sina fält på tacksidan, i Mitt konto och i orderadmin, men inte i ordermejlen. Där behöver båda kassorna samma hjälp. När ordern väl är skapad spelar kassan ingen roll: värdet ligger som metadata på ordern. Filtret woocommerce_email_order_meta_fields lägger till en rad i både kundens och butikens ordermejl. Det enda som skiljer är metanyckeln, så filtret läser båda.
<?php
// Gäller både blockkassan och den klassiska kassan: the order meta exists either way.
add_filter( 'woocommerce_email_order_meta_fields', 'wpu_delivery_instruction_in_emails', 10, 3 );
function wpu_delivery_instruction_in_emails( $fields, $sent_to_admin, $order ) {
$value = $order->get_meta( '_wc_other/wpu/leveransinstruktion' );
if ( '' === $value ) {
$value = $order->get_meta( '_wpu_leveransinstruktion' );
}
if ( '' !== $value ) {
$fields['wpu_leveransinstruktion'] = array(
'label' => 'Leveransinstruktion',
'value' => $value,
);
}
return $fields;
}
Samma mönster använder jag för export till fraktsystem och bokföring: läs metadatan från ordern, inte från kassan.
Alla tre delarna finns färdiga i ett plugin som fungerar med båda kassorna:
Fallgropar
Det vanligaste felet jag ser är kod för fel kassa. Ett woocommerce_checkout_fields-filter i en butik med blockkassan gör ingenting, och ingen felsökning hjälper förrän du inser det. Kontrollera vilken kassa sidan har innan du skriver en rad.
Registrera blockfältet på woocommerce_init, inte i pluginets huvudfil direkt. Körs det för tidigt loggar WooCommerce ett _doing_it_wrong och fältet uteblir.
Id:t i blockkassan måste ha en namnrymd. leveransinstruktion avvisas, wpu/leveransinstruktion fungerar. Namnrymden blir också en del av metanyckeln, så byt den inte efter att butiken fått ordrar.
I den klassiska kassan sparar inte WooCommerce ditt fält åt dig. Glömmer du woocommerce_checkout_create_order visas fältet i kassan men värdet försvinner. Det märks först när kundtjänst frågar var portkoden tog vägen.
När du ska välja något annat
Behöver butiken flera fält, villkor (visa fältet bara vid hemleverans) eller fält som kunden ska kunna ändra efteråt, blir egen kod snabbt mer än en kväll. Då är ett plugin för kassafält ett rimligare val, och det finns flera som stöder båda kassorna. Är det ett enda fält med ett tydligt syfte, som här, är koden ovan hela lösningen.
Vanliga frågor
Hur vet jag vilken kassa min butik använder?
Öppna kassasidan i redigeraren. Innehåller den blocket Kassa (Checkout) är det blockkassan. Innehåller den kortkoden [woocommerce_checkout] är det den klassiska. Nya butiker får blockkassan som standard.
Kan jag använda samma kod för båda kassorna?
Nej, fältet registreras på olika sätt. Det som går att dela är allt som händer efter att ordern skapats: mejl, admin och eventuell export läser orderns metadata, och den finns oavsett kassa. Nyckeln skiljer sig dock, se mejlexemplet.
Sparas värdet när kunden sparar sin adress i Mitt konto?
För fält med location address eller contact i blockkassan, ja. WooCommerce visar och sparar dem under Adresser respektive Kontouppgifter. Fält med location order hör till en enskild order och sparas inte på kunden.
Varför syns inte mitt fält i blockkassan?
Det vanligaste är att registreringen körs för tidigt. Den måste ligga på woocommerce_init eller senare. Det andra är ett id utan namnrymd: id måste skrivas som namnrymd/namn, till exempel wpu/leveransinstruktion.
Källor
- Additional Checkout Fields API, WooCommerce Developer Docs
- CheckoutFields.php (register_checkout_field, validering, metanycklar _wc_other/)
- CheckoutFieldsAdmin.php (fälten i orderadmin)
- CheckoutFieldsFrontend.php (fälten på tacksidan och Mitt konto)
- WC_Checkout: woocommerce_checkout_fields, woocommerce_checkout_create_order
- WC_Emails: woocommerce_email_order_meta_fields
- Customizing checkout fields using actions and filters (klassiska kassan), WooCommerce Developer Docs
