Update_post_meta() не работает при оформлении заказа WooCommerce при отправке заказа

Я создал специальный плагин для своего клиента, но столкнулся с некоторыми проблемами. Я протестировал плагин на своем собственном сайте-песочнице, прежде чем отправить его клиенту, и он работал отлично. Однако на их сайте, который устроен по-другому, я столкнулся с парой проблем.

Один из файлов запускает функции, используя распространенные хуки Woocommerce.

<?php
if (!defined('ABSPATH')) {
    exit;
}

class WC_PM_Checkout_Fields {

    public function __construct() {
        add_action('woocommerce_after_order_notes', array($this, 'add_patient_dropdown_and_custom_fields_to_checkout'), 999);
        add_action('woocommerce_checkout_update_order_meta', array($this, 'save_or_create_patient_on_checkout'), 999);
        add_action('woocommerce_thankyou', array($this, 'display_patient_information_on_thank_you_page'), 999);
        add_action('woocommerce_email_order_meta', array($this, 'add_patient_info_to_order_email'), 999, 3);
        add_action('woocommerce_admin_order_data_after_billing_address', array($this, 'display_patient_fields_in_admin_order'), 999, 1);
    }

    public function add_patient_dropdown_and_custom_fields_to_checkout($checkout) {

        if ( !is_checkout() ) {
            return;
        }

        $args = array(
            'post_type'      => 'patient',
            'author'         => get_current_user_id(),
            'posts_per_page' => -1,
        );

        $patients = new WP_Query($args);

        echo '<div id = "patient_dropdown"><h3>' . __('Select Existing Patient') . '</h3>';
        echo '<select name = "selected_patient_id" id = "selected_patient_id">';
        echo '<option value = "">' . __('Select a patient or enter new details below') . '</option>';

        if ($patients->have_posts()) :
            while ($patients->have_posts()) : $patients->the_post();
                echo '<option value = "' . get_the_ID() . '">' . get_the_title() . '</option>';
            endwhile;
            wp_reset_postdata();
        endif;

        echo '</select></div>';

        echo '<div id = "custom_patient_checkout_fields"><h3>' . __('Or Enter New Patient Information') . '</h3>';

        if (function_exists('woocommerce_form_field')) {
            // First Name field
            woocommerce_form_field('wcpm_patient_first_name', array(
                'type'          => 'text',
                'class'         => array('form-row-wide'),
                'label'         => __('Patient First Name'),
                'required'      => true,
                'placeholder'   => __('Enter patient first name'),
            ), $checkout->get_value('wcpm_patient_first_name'));

            // Last Name field
            woocommerce_form_field('wcpm_patient_last_name', array(
                'type'          => 'text',
                'class'         => array('form-row-wide'),
                'label'         => __('Patient Last Name'),
                'required'      => true,
                'placeholder'   => __('Enter patient last name'),
            ), $checkout->get_value('wcpm_patient_last_name'));

            // Date of Birth field
            woocommerce_form_field('wcpm_patient_dob', array(
                'type'          => 'text',
                'class'         => array('form-row-wide'),
                'label'         => __('Date of Birth'),
                'required'      => true,
                'placeholder'   => __('Select date of birth'),
                'input_class'   => array('datepicker'),
            ), $checkout->get_value('wcpm_patient_dob'));

            // Prescription Dosage field
            woocommerce_form_field('wcpm_patient_dosage', array(
                'type'          => 'text',
                'class'         => array('form-row-wide'),
                'label'         => __('Prescription Dosage'),
                'required'      => true,
                'placeholder'   => __('Enter prescription dosage'),
            ), $checkout->get_value('wcpm_patient_dosage'));

            // Prescription Date field
            woocommerce_form_field('wcpm_patient_prescription_date', array(
                'type'          => 'text',
                'class'         => array('form-row-wide'),
                'label'         => __('Prescription Date'),
                'required'      => true,
                'placeholder'   => __('Select prescription date'),
                'input_class'   => array('datepicker'),
            ), $checkout->get_value('wcpm_patient_prescription_date'));
        }
        echo '</div>';
    }

    public function save_or_create_patient_on_checkout($order_id) {
        $selected_patient_id = !empty($_POST['selected_patient_id']) ? intval($_POST['selected_patient_id']) : null;
        $patient_first_name = sanitize_text_field($_POST['wcpm_patient_first_name']);
        $patient_last_name = sanitize_text_field($_POST['wcpm_patient_last_name']);
        $patient_dob = !empty($_POST['wcpm_patient_dob']) ? date('Y-m-d', strtotime(str_replace('/', '-', $_POST['wcpm_patient_dob']))) : '';
        $patient_dosage = sanitize_text_field($_POST['wcpm_patient_dosage']);
        $patient_prescription_date = !empty($_POST['wcpm_patient_prescription_date']) ? date('Y-m-d', strtotime(str_replace('/', '-', $_POST['wcpm_patient_prescription_date']))) : '';

        if ($selected_patient_id) {
            // An existing patient was selected
            $patient_id = $selected_patient_id;
        } else {
            // Create a new patient post
            $patient_title = $patient_first_name . ' ' . $patient_last_name;
            $current_user_id = get_current_user_id();
    
            $existing_patient = get_posts(array(
                'post_type'  => 'patient',
                'author'     => $current_user_id,
                'post_status'=> 'publish',
                'meta_query' => array(
                    array(
                        'key'     => 'wcpm_patient_first_name',
                        'value'   => ucwords($patient_first_name),
                        'compare' => '='
                    ),
                    array(
                        'key'     => 'wcpm_patient_last_name',
                        'value'   => ucwords($patient_last_name),
                        'compare' => '='
                    )
                )
            ));
    
            if ($existing_patient) {
                $patient_id = $existing_patient[0]->ID;
            } else {
                $patient_post = array(
                    'post_title'  => $patient_title,
                    'post_type'   => 'patient',
                    'post_status' => 'publish',
                    'post_author' => $current_user_id,
                );
    
                $patient_id = wp_insert_post($patient_post);
    
                // Save the custom fields for the new patient
                update_post_meta($patient_id, 'wcpm_patient_first_name', ucwords($patient_first_name));
                update_post_meta($patient_id, 'wcpm_patient_last_name', ucwords($patient_last_name));
                update_post_meta($patient_id, 'wcpm_patient_dob', $patient_dob);
            }
        }
    
        // Save patient information to the order meta
        update_post_meta($order_id, '_selected_patient_id', $patient_id);
        update_post_meta($order_id, 'wcpm_patient_first_name', ucwords($patient_first_name));
        update_post_meta($order_id, 'wcpm_patient_last_name', ucwords($patient_last_name));
        update_post_meta($order_id, 'wcpm_patient_dob', $patient_dob);
        update_post_meta($order_id, 'wcpm_patient_dosage', $patient_dosage);
        update_post_meta($order_id, 'wcpm_patient_prescription_date', $patient_prescription_date);
    }    

    public function display_patient_information_on_thank_you_page($order_id) {
        $selected_patient_id = get_post_meta($order_id, '_selected_patient_id', true);
    
        if ($selected_patient_id) {
            $patient_first_name = get_post_meta($selected_patient_id, 'wcpm_patient_first_name', true);
            $patient_last_name = get_post_meta($selected_patient_id, 'wcpm_patient_last_name', true);
            $patient_dob = get_post_meta($selected_patient_id, 'wcpm_patient_dob', true);
        } else {
            $patient_first_name = get_post_meta($order_id, 'wcpm_patient_first_name', true);
            $patient_last_name = get_post_meta($order_id, 'wcpm_patient_last_name', true);
            $patient_dob = get_post_meta($order_id, 'wcpm_patient_dob', true);
        }

        $patient_dosage = get_post_meta($order_id, 'wcpm_patient_dosage', true);
        $patient_prescription_date = get_post_meta($order_id, 'wcpm_patient_prescription_date', true);
    
        $dob_formatted = !empty($patient_dob) ? date('d/m/Y', strtotime($patient_dob)) : '';
        $prescription_date_formatted = !empty($patient_prescription_date) ? date('d/m/Y', strtotime($patient_prescription_date)) : '';
    
        echo '<h2>' . __('Patient Information') . '</h2>';
        echo '<p><strong>' . __('First Name') . ':</strong> ' . esc_html(ucwords($patient_first_name)) . '</p>';
        echo '<p><strong>' . __('Last Name') . ':</strong> ' . esc_html(ucwords($patient_last_name)) . '</p>';
        echo '<p><strong>' . __('Date of Birth') . ':</strong> ' . esc_html($dob_formatted) . '</p>';
        echo '<p><strong>' . __('Prescription Dosage') . ':</strong> ' . esc_html($patient_dosage) . '</p>';
        echo '<p><strong>' . __('Prescription Date') . ':</strong> ' . esc_html($prescription_date_formatted) . '</p>';
    }    
    
    public function add_patient_info_to_order_email($order, $sent_to_admin, $plain_text) {
        $this->display_patient_information_on_thank_you_page($order->get_id());
    }    

    public function display_patient_fields_in_admin_order($order) {
        $this->display_patient_information_on_thank_you_page($order->get_id());
    }
}

new WC_PM_Checkout_Fields();

Первая функция добавляет дополнительные поля, которые можно заполнить либо путем ввода новой информации, либо с помощью раскрывающегося списка, который извлекает информацию из пользовательского типа сообщения.

После отправки заказа создается новый пациент, если он еще не существует, и все эти дополнительные поля добавляются на страницу подтверждения, в электронное письмо и метаданные заказа. Однако метаданные заказа, похоже, не обновляются, поэтому отображаются имена полей, но не значения.

Я создал тестовую функцию, которая работает только с «admin_init», и добавил свой собственный order_id, и это сработало отлично. Что-то вызывает конфликт, но причину найти не удается.

Плагины на сайте:

  • Расширенные пользовательские поля PRO
  • Расширенное отслеживание отправлений Pro
  • Авада Строитель
  • Авада Ядро
  • Фрагменты кода
  • Пользовательские поля регистрации пользователей для WooCommerce
  • Проверка цифровой подписи для Woocommerce
  • Дубликатор
  • Проверка личности для WooCommerce
  • Перенаправление
  • Остановить перечисление пользователей
  • TrackShip для WooCommerce
  • Редактор ролей пользователей
  • WooCommerce для зарегистрированных пользователей
  • Платежный пакет WooCommerce Opayo
  • WooCommerce Запир
  • Электронная коммерция Worldpay для WooCommerce
  • Самый быстрый кеш WP
  • WP Почта SMTP
  • Йост SEO

Я проверил фрагменты кода, но не нашел там ничего, что могло бы вызвать проблемы. Я раньше не пользовался Авадой.

🤔 А знаете ли вы, что...
PHP можно использовать для создания API и веб-служб.


2
50
1

Ответ:

Решено

Прежде всего обратите внимание, что Высокопроизводительное хранилище заказов (HPOS) теперь включено по умолчанию в WooCommerce и требует использования некоторых других перехватчиков с методами получения и установки объектов CRUD вместо метафункций WordPress Post.

Кроме того, убедитесь, что ваш клиент не использует новые блоки оформления заказа, которые не позволяют выполнять подобные настройки.

Для начала попробуйте заменить старый крючок woocommerce_checkout_update_order_meta из:

add_action('woocommerce_checkout_update_order_meta', array($this, 'save_or_create_patient_on_checkout'), 999);

с:

add_action('woocommerce_checkout_create_order', array($this, 'save_or_create_patient_on_checkout'), 10, 1 );

Затем замените связанную функцию чем-то вроде (аргументом функции теперь является $order, который является объектом WC_order):

public function save_or_create_patient_on_checkout( $order ) {
    $selected_patient_id = !empty($_POST['selected_patient_id']) ? intval($_POST['selected_patient_id']) : null;
    $patient_first_name = sanitize_text_field($_POST['wcpm_patient_first_name']);
    $patient_last_name = sanitize_text_field($_POST['wcpm_patient_last_name']);
    $patient_dob = !empty($_POST['wcpm_patient_dob']) ? date('Y-m-d', strtotime(str_replace('/', '-', $_POST['wcpm_patient_dob']))) : '';
    $patient_dosage = sanitize_text_field($_POST['wcpm_patient_dosage']);
    $patient_prescription_date = !empty($_POST['wcpm_patient_prescription_date']) ? date('Y-m-d', strtotime(str_replace('/', '-', $_POST['wcpm_patient_prescription_date']))) : '';

    if ($selected_patient_id) {
        // An existing patient was selected
        $patient_id = $selected_patient_id;
    } else {
        // Create a new patient post
        $patient_title = $patient_first_name . ' ' . $patient_last_name;
        $current_user_id = get_current_user_id();

        $existing_patient = get_posts(array(
            'post_type'  => 'patient',
            'author'     => $current_user_id,
            'post_status'=> 'publish',
            'meta_query' => array(
                array(
                    'key'     => 'wcpm_patient_first_name',
                    'value'   => ucwords($patient_first_name),
                    'compare' => '='
                ),
                array(
                    'key'     => 'wcpm_patient_last_name',
                    'value'   => ucwords($patient_last_name),
                    'compare' => '='
                )
            )
        ));

        if ($existing_patient) {
            $patient_id = $existing_patient[0]->ID;
        } else {
            $patient_post = array(
                'post_title'  => $patient_title,
                'post_type'   => 'patient',
                'post_status' => 'publish',
                'post_author' => $current_user_id,
            );

            $patient_id = wp_insert_post($patient_post);

            // Save the custom fields for the new patient
            update_post_meta($patient_id, 'wcpm_patient_first_name', ucwords($patient_first_name));
            update_post_meta($patient_id, 'wcpm_patient_last_name', ucwords($patient_last_name));
            update_post_meta($patient_id, 'wcpm_patient_dob', $patient_dob);
        }
    }

    // Save patient information as order metadata (compatible with HPOS)
    $order->update_meta_data('_selected_patient_id', $patient_id);
    $order->update_meta_data('wcpm_patient_first_name', ucwords($patient_first_name));
    $order->update_meta_data('wcpm_patient_last_name', ucwords($patient_last_name));
    $order->update_meta_data('wcpm_patient_dob', $patient_dob);
    $order->update_meta_data('wcpm_patient_dosage', $patient_dosage);
    $order->update_meta_data('wcpm_patient_prescription_date', $patient_prescription_date);
}

Чтобы сделать отображение страницы благодарности совместимым с HPOS, замените соответствующую функцию на:

public function display_patient_information_on_thank_you_page($order_id) {
    $order = wc_get_order($order_id); // Get the WC_Order object

    $selected_patient_id = $order->get_meta('_selected_patient_id'); // HPOS compatible

    if ($selected_patient_id) {
        $patient_first_name = get_post_meta($selected_patient_id, 'wcpm_patient_first_name', true);
        $patient_last_name = get_post_meta($selected_patient_id, 'wcpm_patient_last_name', true);
        $patient_dob = get_post_meta($selected_patient_id, 'wcpm_patient_dob', true);
    } else {
        $patient_first_name = $order->get_meta('wcpm_patient_first_name'); // HPOS compatible
        $patient_last_name = $order->get_meta('wcpm_patient_last_name'); // HPOS compatible
        $patient_dob = $order->get_meta('wcpm_patient_dob'); // HPOS compatible
    }

    $patient_dosage = $order->get_meta('wcpm_patient_dosage'); // HPOS compatible
    $patient_prescription_date = $order->get_meta('wcpm_patient_prescription_date'); // HPOS compatible

    $dob_formatted = !empty($patient_dob) ? date('d/m/Y', strtotime($patient_dob)) : '';
    $prescription_date_formatted = !empty($patient_prescription_date) ? date('d/m/Y', strtotime($patient_prescription_date)) : '';

    echo '<h2>' . __('Patient Information') . '</h2>';
    echo '<p><strong>' . __('First Name') . ':</strong> ' . esc_html(ucwords($patient_first_name)) . '</p>';
    echo '<p><strong>' . __('Last Name') . ':</strong> ' . esc_html(ucwords($patient_last_name)) . '</p>';
    echo '<p><strong>' . __('Date of Birth') . ':</strong> ' . esc_html($dob_formatted) . '</p>';
    echo '<p><strong>' . __('Prescription Dosage') . ':</strong> ' . esc_html($patient_dosage) . '</p>';
    echo '<p><strong>' . __('Prescription Date') . ':</strong> ' . esc_html($prescription_date_formatted) . '</p>';
}

Теперь ваш код совместим с высокопроизводительным хранилищем заказов и должен работать как с включенным HPOS, так и без него.

Итак, подведем итог: метаданные заказов WooCommerce:

  • Для чтения метаданных используйте метод get_meta() из объекта WC_Order.
  • Для обновления метаданных используйте метод update_meta_data() из объекта WC_Order.

При обновлении метаданных заказа требуется метод save(), за исключением:

  • woocommerce_checkout_create_order крюк действия, как он будет включен позже.