I have a website under WordPress 6.7.1 with WooCommerce 9.6.1. I use the following code to add and save some custom checkout fields:
/**
* 1️⃣ Add custom fields to WooCommerce checkout
*/
add_filter('woocommerce_checkout_fields', function ($fields) {
$fields['billing']['player_id'] = [
'type' => 'text',
'label' => 'DNI Jugador',
'required' => true,
'class' => ['form-row-wide'],
'priority' => 20,
];
$fields['billing']['dad_name'] = [
'type' => 'text',
'label' => 'Nombre Padre/Madre/Tutor',
'required' => true,
'class' => ['form-row-wide'],
'priority' => 25,
];
$fields['billing']['dad_id'] = [
'type' => 'text',
'label' => 'DNI Padre/Madre/Tutor',
'required' => true,
'class' => ['form-row-wide'],
'priority' => 30,
];
$fields['billing']['player_birthdate'] = [
'type' => 'date',
'label' => 'Fecha de Nacimiento',
'required' => true,
'class' => ['form-row-wide'],
'priority' => 40,
];
$fields['billing']['player_team'] = [
'type' => 'text',
'label' => 'Equipo en el que juegas',
'required' => false,
'class' => ['form-row-wide'],
'priority' => 50,
];
$fields['billing']['player_adult'] = [
'type' => 'select',
'label' => '¿Eres mayor de edad?',
'required' => true,
'options' => [
'' => 'Selecciona una opción',
'yes' => 'Sí',
'no' => 'No',
],
'class' => ['form-row-wide'],
'priority' => 60,
];
$fields['billing']['pictures_consent'] = [
'type' => 'select',
'label' => 'Con la inclusión de las nuevas tecnologías dentro del mundo del deporte y ante la posibilidad de que en estas puedan aparecer imágenes de vuestros hijos/as durante la realización de las actividades deportivas. Y dado que el derecho a la propia imagen está reconocido al articulo 18 de la Constitución y regulado por la Ley 1/1982, de 5 de mayo, sobre el derecho al honor, a la intimidad personal y familiar y a la propia imagen y la Ley 15/1999, de 13 de diciembre, sobre la Protección de Datos de Carácter Personal. Timeout Workouts pide el consentimiento a los padres o tutores legales para poder publicar las imágenes en las cuales aparezcan individualmente o en grupo, que con carácter informativo se puedan realizar a los jugadores/as participantes en nuestras actividades.',
'required' => true,
'options' => [
'' => 'Selecciona una opción',
'yes' => 'Sí',
'no' => 'No',
],
'class' => ['form-row-wide'],
'priority' => 70,
];
$fields['billing']['player_allergies'] = [
'type' => 'textarea',
'label' => 'Alergias o enfermedades',
'required' => false,
'class' => ['form-row-wide'],
'priority' => 80,
];
$fields['billing']['player_medicine'] = [
'type' => 'textarea',
'label' => 'Medicamentos',
'required' => false,
'class' => ['form-row-wide'],
'priority' => 90,
];
$fields['billing']['player_video'] = [
'type' => 'text',
'label' => '¡Queremos conocerte! Te podemos ver jugar con un Link a un vídeo',
'required' => true,
'class' => ['form-row-wide'],
'priority' => 100,
];
$fields['billing']['player_shirt'] = [
'type' => 'select',
'label' => 'Talla de camiseta',
'required' => true,
'options' => [
'' => 'Selecciona una opción',
's' => 'S',
'm' => 'M',
'l' => 'L',
'xl' => 'XL',
'xxl' => 'XXL',
],
'class' => ['form-row-wide'],
'priority' => 110,
];
$fields['billing']['how_meet_us'] = [
'type' => 'select',
'label' => '¿Cómo nos has conocido?',
'required' => true,
'options' => [
'' => 'Selecciona una opción',
'social' => 'Redes sociales',
'friends' => 'Amigos',
'other' => 'Otros',
],
'class' => ['form-row-wide'],
'priority' => 120,
];
$fields['billing']['payment_times'] = [
'type' => 'select',
'label' => '¿En cuántas cuotas deseas pagar?',
'required' => true,
'options' => [
'' => 'Selecciona una opción',
'1' => 'Pago unico',
'2' => '2 Pagos fraccionados',
],
'class' => ['form-row-wide'],
'priority' => 130,
];
return $fields;
});
/**
* 2️⃣ Save custom checkout fields to order meta
*/
add_action('woocommerce_checkout_update_order_meta', function ($order_id) {
$order = wc_get_order($order_id); // Obtener el objeto de la orden
$fields = [
'player_id',
'dad_id',
'dad_name',
'player_birthdate',
'player_team',
'player_adult',
'pictures_consent',
'player_allergies',
'player_medicine',
'player_video',
'player_shirt',
'how_meet_us',
'payment_times',
];
foreach ($fields as $field) {
if ( isset( $_POST[ $field ] ) && ! empty( $_POST[ $field ] ) ) {
$order->update_meta_data( $field, sanitize_text_field( $_POST[ $field ] ) );
}
}
$order->save(); // Guardar la orden
});
It works fine, and I am able to see that all related custom metadata in the order details page, in the custom fields section (see the screenshot below):
The data is being stored correctly and I can see it there.
The problem is when I try to show it on my all orders page. I want a new column for each of these custom fields. For that, I had this code
/**
* 3️⃣ Display custom fields in WooCommerce order details page
*/
add_action('woocommerce_admin_order_data_after_billing_address', function ($order) {
echo '<h3>Información del Jugador</h3>';
$fields = [
'player_id' => 'DNI Jugador',
'dad_id' => 'DNI Padre/Madre/Tutor',
'dad_name' => 'Nombre del Padre/Madre/Tutor',
'player_birthdate' => 'Fecha de Nacimiento',
'player_team' => 'Equipo',
'player_adult' => 'Mayor de Edad',
'pictures_consent' => 'Consentimiento Fotos',
'player_allergies' => 'Alergias o enfermedades',
'player_medicine' => 'Medicamentos',
'player_video' => 'Vídeo jugando',
'player_shirt' => 'Talla camiseta',
'how_meet_us' => '¿Cómo nos has conocido?',
'payment_times' => 'Número de cuotas para el pago',
];
foreach ($fields as $key => $label) {
$value = $order->get_meta($field);
if (!empty($value)) {
echo "<p><strong>$label:</strong> " . esc_html($value) . "</p>";
}
}
});
/**
* 4️⃣ Add custom columns to WooCommerce orders table (HPOS compatible)
*/
add_filter('woocommerce_shop_order_list_table_columns', function ($columns) {
// Define los nuevos campos
$fields = [
'player_id' => 'DNI Jugador',
'dad_id' => 'DNI Padre/Madre/Tutor',
'dad_name' => 'Nombre del Padre/Madre/Tutor',
'player_birthdate' => 'Fecha de Nacimiento',
'player_team' => 'Equipo',
'player_adult' => 'Mayor de Edad',
'pictures_consent' => 'Consentimiento Fotos',
'player_allergies' => 'Alergias o enfermedades',
'player_medicine' => 'Medicamentos',
'player_video' => 'Vídeo jugando',
'player_shirt' => 'Talla camiseta',
'how_meet_us' => '¿Cómo nos has conocido?',
'payment_times' => 'Número de cuotas para el pago',
];
// Insertar las nuevas columnas después de la columna 'order_total'
$new_columns = [];
foreach ($columns as $key => $value) {
$new_columns[$key] = $value;
if ('order_total' === $key) {
foreach ($fields as $field_key => $field_label) {
$new_columns[$field_key] = $field_label;
}
}
}
return $new_columns;
}, 20);
add_action('woocommerce_shop_order_list_table_custom_column', function ($column, $order) {
// Definir los campos a mostrar
$fields = [
'player_id' => 'DNI Jugador',
'dad_id' => 'DNI Padre/Madre/Tutor',
'dad_name' => 'Nombre del Padre/Madre/Tutor',
'player_birthdate' => 'Fecha de Nacimiento',
'player_team' => 'Equipo',
'player_adult' => 'Mayor de Edad',
'pictures_consent' => 'Consentimiento Fotos',
'player_allergies' => 'Alergias o enfermedades',
'player_medicine' => 'Medicamentos',
'player_video' => 'Vídeo jugando',
'player_shirt' => 'Talla camiseta',
'how_meet_us' => '¿Cómo nos has conocido?',
'payment_times' => 'Número de cuotas para el pago',
];
// Mostrar los valores de los campos personalizados
if (isset($fields[$column])) {
$value = $order->get_meta($field);
echo !empty($value) ? esc_html($value) : '—';
}
}, 10, 2);
Which at some point worked, but now I don’t know why it shows a “-” in every field. The columns are being added correctly to the table, but the are all empty. I’ve tried a lot of things with no success. Need to clarify that I’m new with php and Woocommerce and this code is mostly AI-generated. Also, a couple of days ago, Woocommerce was updated, but I have only found that the changes are the logo and colors, so it shouldn’t have affected my site, but who knows. I think that before the update (or at least when it worked) these custom fields did not appear where they do now in the order’s detail page. Don’t know if that’s relevant.
