• Никакой политики на форуме. Иначе - бан!
  • Вопрос без рабочей ссылки на проблему считается риторическим. Без ссылки и скриншота - провокацией!
  • Темы озаглавленные с маленькой буквы или капсом удаляются без предупреждения!

Решено Как избавится от заполнения всех полей при Самовывозе?

roman001

Новичок
Нужно что бы при выборе самовывоз отображались ТОЛЬКО поля: ИМЯ, ФАМИЛИЯ, ТЕЛЕФОН, EMAIL (добавить - я добавил уже, но как убрать другие поля? ненужные)
Поля: АДРЕС, СТРАНА, НАСЕЛЕННЫЙ ПУНКТ, ОБЛАСТЬ/РЕГИОН, ПОЧТОВЫЙ ИНДЕКС, ПРИМЕЧАНИЯ К ЗАКАЗУ - нужно убрать со страницы ОФОРМЛЕНИЕ ЗАКАЗА при выборе: Cамовывоз

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

Если можно то код целиком.

Clip2net_180805005512.png

С уважением Роман
 

rred

Новичок
осталась главная проблема - как убрать не нужные поля из самовывоза?
Весь изюм как раз был в том, что привязанные к доставке поля пропадают из общего блока, а у Вас они дублируются, это странно и пока непонятно. А Вы точно весь код целиком скопировали? Проверьте пожалуйста, наличие строк
add_action('woocommerce_before_cart_totals', 'smf_before_checkout_form');
add_action('woocommerce_before_checkout_form', 'smf_before_checkout_form'); ?
add_filter('woocommerce_checkout_fields', 'smf_remove_checkout_fields');
 

roman001

Новичок
Весь изюм как раз был в том, что привязанные к доставке поля пропадают из общего блока, а у Вас они дублируются, это странно и пока непонятно. А Вы точно весь код целиком скопировали? Проверьте пожалуйста, наличие строк
add_action('woocommerce_before_cart_totals', 'smf_before_checkout_form');
add_action('woocommerce_before_checkout_form', 'smf_before_checkout_form'); ?
add_filter('woocommerce_checkout_fields', 'smf_remove_checkout_fields');
Этих строк нет.
Но их нет и у вас в коде.

А нет нашел. Есть они. Эти строки.
 
Последнее редактирование:

roman001

Новичок
Вот код который я копирую и вставляю:

Код:
/**
* Настройка привязки полей к методам доставки.
*
* Функция возвращает массив полей заказа, которые актуальны
* только для указанных методов доставки и неприменимы для других методов.
*
* Указанные в массиве поля не будут отображаться в стандартных блоках оплаты и доставки.
* Вместо этого они будут выведены после наименования метода доставки
* и только когда он выбран.
*
* Если к определённому виду доставки привязано обязательное поле, но
* выбрана другая доставка, проблем с валидацией не будет, поскольку
* в этом случае поле исключается из обрабатываемых полей стандартным способом.
*
* Массив двумерный: поля сгруппированы по блокам, в соответствии с документацией
* https://docs.woocommerce.com/document/tutorial-customising-checkout-fields-using-actions-and-filters/#section-2
*
* Например, как сделать, чтобы поля адреса были применимы
* только к методу доставки "Единая ставка":
*
       return array(
         'billing' => array(
             'billing_address_1' => array( 'flat_rate' ),
             'billing_address_2' => array( 'flat_rate' )
         )
       );
*/
function get_shipping_method_fields() {
    return array(
        'billing' => array(
            'billing_address_1' => array( 'flat_rate' ),
            'billing_address_2' => array( 'flat_rate' ),
            'billing_postcode' => array( 'local_pickup' ),
        )
    );
}
/**
* Проверяет наличие метода доставки в формате типа 'flat_rate:3'
* в массиве методов доставки (method_id - в формате типа 'flat_rate' )
*
* @param type $chosen_shipping
* @param type $methods
* @return type
*/
function in_methods_array($chosen_shipping_id, $method_ids)
{
    $found = FALSE;
    $i = 0;
    $count = count($method_ids);
    while ( !$found && ( $i < $count ) ){
        $method_id = $method_ids[$i];
        $found = ( strpos($chosen_shipping_id, $method_id) !== FALSE );
        $i++;
    }
    return $found;
}

/**
* Скрыть в корзине и блоках оплаты и доставки поля,
* которые имеют привязку к методам доставки.
* Установленная переменная используется в фильтре woocommerce_checkout_fields
*/
add_action('woocommerce_before_cart_totals',  'smf_before_checkout_form');
add_action('woocommerce_before_checkout_form',  'smf_before_checkout_form');
function smf_before_checkout_form(){
       set_query_var( 'smf_hide_fields', TRUE );
}
add_action('woocommerce_after_checkout_form',  'smf_after_checkout_form');
add_action('woocommerce_after_cart_totals',  'smf_after_checkout_form');
function smf_after_checkout_form(){
       set_query_var( 'smf_hide_fields', FALSE );
}

/**
* Отключить неприменимые к текущему методу доставки поля.
* Или отключить всё поля, привязанные к методам доставки,
* если идёт вывод checkout_form
*/
add_filter('woocommerce_checkout_fields', 'smf_remove_checkout_fields');
function smf_remove_checkout_fields($fields) {
    $smf_fields = get_shipping_method_fields();
    if ( !empty( $smf_fields ) ){
        $hideall = get_query_var('smf_hide_fields') === TRUE;
        $chosen_methods = WC()->session->get( 'chosen_shipping_methods' );
        $chosen_shipping_id = $chosen_methods[0];
        foreach ( $fields as $fieldset => $fieldlist ) {
            if ( key_exists( $fieldset, $smf_fields ) ) {
                foreach ( $fieldlist as $fieldkey => $field ) {
                    if ( key_exists($fieldkey, $smf_fields[$fieldset] ) ){

                        $method_ids = $smf_fields[$fieldset][$fieldkey];
                        if ( $hideall || !in_methods_array($chosen_shipping_id, $method_ids) ){

                            unset( $fields[$fieldset][$fieldkey] );

                        }
                    }
                }
            }
        }
    }
  
    return $fields;
}

/**
*  Вывести поля для метода доставки, если он выбран в данный момент
*/
add_action('woocommerce_after_shipping_rate', 'smf_after_shipping_rate');
function smf_after_shipping_rate( $method ) {
    $chosen_methods = WC()->session->get( 'chosen_shipping_methods' );
    $chosen_shipping_id = $chosen_methods[0];

    $smf_fields = get_shipping_method_fields();
    if ( !empty( $smf_fields ) ){

        // это выбранный метод доставки?
        if ( strpos($chosen_shipping_id, $method->id) !== FALSE ){
          
            $checkout = WC()->checkout;
            foreach ($smf_fields as $fieldset => $fieldlist) {
                $allfields = $checkout->get_checkout_fields( $fieldset );
                $fieldkeys = array_keys($fieldlist);
                foreach ( $allfields as $fieldkey => $field ) {
                    $method_ids = $smf_fields[$fieldset][$fieldkey];
                    if (
                            in_array($fieldkey, $fieldkeys) &&
                            in_methods_array($chosen_shipping_id, $method_ids)
                       )
                    {
                        woocommerce_form_field( $fieldkey, $field, $checkout->get_value( $fieldkey ) );
                    }
                }
              
            }
        }
    }
}
 

rred

Новичок
Всё правильно, код рабочий, просто после редактирования функции в functions.php надо "обновить" страницу оформления заказа и всё встанет на свои места.
 

marr

Специалист
Местный
Спасибо большое вам за труд.

А я использовала скрип с stackoverflow.com
Доработала его под нужды своего сайта. У меня 4 метода доставки (в данном скрипте только 2).
Я добавила свои условия, у меня в каждом из 4-х случаев видны разные поля в зависимости от метода доставки.
 
Последнее редактирование:

Matte Bud

Новичок
А я использовала вот этот скрипт: ссылка на stackoverflow.com
Доработала его под нужды своего сайта. У меня 4 метода доставки (в данном скрипте только 2).
Я добавила свои условия, у меня в каждом из 4-х случаев видны разные поля в зависимости от метода доставки.

Сайт, на котором сейчас это поставила, можете посмотреть (положите товар в корзину и перейдите на оформление, только прошу не подтвержать заказ - магазин работающий !): http://volga-21.ru/checkout/

Единственное с чем пока не разобралась - это слово "необязательно", которое появилось рядом со звездочкой. Это фишка последнего релиза woocommerce. Пока в раздумьях откатить до предыдущего релиза или писать скрипт, который исправит это).
Подскажите пожалуйста, как вы поле Населенный Пункт удалили из формы заказа при активном самовывозе?
 

marr

Специалист
Местный
Подскажите пожалуйста, как вы поле Населенный Пункт удалили из формы заказа при активном самовывозе?
Скриптом проверяю, какой выбран метод доставки. И показываю только нужные поля для этого метода.
 
Последнее редактирование:

Matte Bud

Новичок
Скриптом проверяю, какой выбран метод доставки. И показываю только нужные поля для этого метода. Добавила в скрипт с stackoverflow.com свои поля
А можете привести пример как добавили список всех своих полей в скрипт.

Я решил свой вопрос вот так) Просто вставив после вашего кода:

/*
* Убираем поля для конкретного способа доставки
*/
add_filter( 'woocommerce_checkout_fields', 'awoohc_override_checkout_fields' );
function awoohc_override_checkout_fields( $fields ) {
// получаем выбранные метод доставки
$chosen_methods = WC()->session->get( 'chosen_shipping_methods' );
// проверяем текущий метод и убираем не ненужные поля
if ( 'local_pickup:3' === $chosen_methods[0] ) {
unset( $fields['billing']['billing_city'] );

}

return $fields;
}
 

marr

Специалист
Местный
У меня через jQuery, просто добавила к тем полям что в скрипте еще несколько своих.
 

Matte Bud

Новичок
У меня через jQuery, просто добавила к тем полям что в скрипте еще несколько своих.
К этим полям добавить надо свои?
showHide('show',b1 ); // Country
showHide('hide',b2 ); // Address 1
showHide('hide',b3 ); // Address 2
showHide('hide',b4 ); // Postcode
showHide('hide',b5 ); // State
Или к этим?
$chosen_shipping_method = WC()->session->get( 'chosen_shipping_methods' )[0];
$billing = '<strong> ' . __('Billing', 'woocommerce') . ' ';
$shipping = '<strong> ' . __('Shipping', 'woocommerce') . ' ';
$country = __('country.', 'woocommerce');
$address1 = __('address.', 'woocommerce');
$postcode = __('postcode.', 'woocommerce');
$state = __('state.', 'woocommerce');
$end_text = '</strong> '. __('is a required field.', 'woocommerce');
 
Последнее редактирование:

alexey211191

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

Этой теме уже 4 года, прочитал её всю внимательно, как и ещё 100500 хаков по данному вопросу. И вот к чему пришёл. Проблема терзает людей до сих пор и все в едином порыве смотрят в сторону "магии jQuery". По всему выходит, что разработчики WooCommerce что-то недоработали или скоро доработают. Ведь блок с заказом и доставкой обновляется аяксом, а поля - нет. Значит, рано или поздно должны доработать. Ничего подобного, не должны и не доработают. Поскольку логика формы заказа цельная и здравая: сначала пользователь указывает кому и куда, а потом разбирается с доставкой и оплатой. При всём уважении к yaspis и действительно работающему методу, это костыль. А костыль - это не дело.

Посудите сами. Если у вас по умолчанию Самовывоз, пользователь пишет только ФИО и контакты. Далее он смотрит на варианты доставки, а там можно ещё и курьером. Он думает: "Хм.. а пусть будет лучше курьером". Он жмёт на "Курьерская доставка" и... тадам! Где-то там наверху появляются новые поля с адресом! Теперь пользователю надо к ним вернуться и заполнить. Если он их сразу заметит, конечно. Это неудобно, это нелогично. Пользователь не должен метаться туда-обратно, заполнение полей должно происходить строго в порядке их следования. И решение здесь может быть только одно: выбрав метод доставки, требующий дополнительных данных, пользователь должен увидеть их здесь же, сразу под названием выбранной доставки.

На самом деле, не нужно писать JavaScript, не нужно отключать обязательность полей, не нужно даже лезть в шаблоны. В WC уже всё есть, чтобы достаточно просто реализовать описанный товарищем studnet функционал.

Действительно:
1) Вывод дополнительной информации к методу доставки - событие woocommerce_after_shipping_rate
2) Отключение ненужных полей - фильтр woocommerce_checkout_fields
3) Получить текущий выбранный метод доставки - WC()->session->get( 'chosen_shipping_methods' );
4) Вывод полей начинается с woocommerce_before_checkout_form и заканчивается woocommerce_after_checkout_form
5) Отображение итогов корзины, соответственно - woocommerce_before_cart_totals и woocommerce_after_cart_totals
6) Поле отображается на странице функцией woocommerce_form_field

Это всё, что нам нужно, остальное - дело техники. Приведённый ниже код можно скопировать в functions.php вашей темы и он сразу работает. Должен, во всяком случае (WooCommerce 3.4.4). Для тестирования у вас должно быть два метода доставки "Единая ставка" (flat_rate) и "Самовывоз" (local_pickup). Для первого метода будут показаны поля адреса, а для второго - индекс. Это для теста, настройка вся вынесена в функцию "get_shipping_method_fields()". В ней вы можете указывать как метод доставки в формате "flat_rate", так и выделить конкретный метод: "flat_rate:5". Работает и так и эдак.


Код:
/**
* Настройка привязки полей к методам доставки.
*
* Функция возвращает массив полей заказа, которые актуальны
* только для указанных методов доставки и неприменимы для других методов.
*
* Указанные в массиве поля не будут отображаться в стандартных блоках оплаты и доставки.
* Вместо этого они будут выведены после наименования метода доставки
* и только когда он выбран.
*
* Если к определённому виду доставки привязано обязательное поле, но
* выбрана другая доставка, проблем с валидацией не будет, поскольку
* в этом случае поле исключается из обрабатываемых полей стандартным способом.
*
* Массив двумерный: поля сгруппированы по блокам, в соответствии с документацией
* https://docs.woocommerce.com/document/tutorial-customising-checkout-fields-using-actions-and-filters/#section-2
*
* Например, как сделать, чтобы поля адреса были применимы
* только к методу доставки "Единая ставка":
*
       return array(
         'billing' => array(
             'billing_address_1' => array( 'flat_rate' ),
             'billing_address_2' => array( 'flat_rate' )
         )
       );
*/
function get_shipping_method_fields() {
    return array(
        'billing' => array(
            'billing_address_1' => array( 'flat_rate' ),
            'billing_address_2' => array( 'flat_rate' ),
            'billing_postcode' => array( 'local_pickup' ),
        )
    );
}
/**
* Проверяет наличие метода доставки в формате типа 'flat_rate:3'
* в массиве методов доставки (method_id - в формате типа 'flat_rate' )
*
* @param type $chosen_shipping
* @param type $methods
* @return type
*/
function in_methods_array($chosen_shipping_id, $method_ids)
{
    $found = FALSE;
    $i = 0;
    $count = count($method_ids);
    while ( !$found && ( $i < $count ) ){
        $method_id = $method_ids[$i];
        $found = ( strpos($chosen_shipping_id, $method_id) !== FALSE );
        $i++;
    }
    return $found;
}

/**
* Скрыть в корзине и блоках оплаты и доставки поля,
* которые имеют привязку к методам доставки.
* Установленная переменная используется в фильтре woocommerce_checkout_fields
*/
add_action('woocommerce_before_cart_totals',  'smf_before_checkout_form');
add_action('woocommerce_before_checkout_form',  'smf_before_checkout_form');
function smf_before_checkout_form(){
       set_query_var( 'smf_hide_fields', TRUE );
}
add_action('woocommerce_after_checkout_form',  'smf_after_checkout_form');
add_action('woocommerce_after_cart_totals',  'smf_after_checkout_form');
function smf_after_checkout_form(){
       set_query_var( 'smf_hide_fields', FALSE );
}

/**
* Отключить неприменимые к текущему методу доставки поля.
* Или отключить всё поля, привязанные к методам доставки,
* если идёт вывод checkout_form
*/
add_filter('woocommerce_checkout_fields', 'smf_remove_checkout_fields');
function smf_remove_checkout_fields($fields) {
    $smf_fields = get_shipping_method_fields();
    if ( !empty( $smf_fields ) ){
        $hideall = get_query_var('smf_hide_fields') === TRUE;
        $chosen_methods = WC()->session->get( 'chosen_shipping_methods' );
        $chosen_shipping_id = $chosen_methods[0];
        foreach ( $fields as $fieldset => $fieldlist ) {
            if ( key_exists( $fieldset, $smf_fields ) ) {
                foreach ( $fieldlist as $fieldkey => $field ) {
                    if ( key_exists($fieldkey, $smf_fields[$fieldset] ) ){

                        $method_ids = $smf_fields[$fieldset][$fieldkey];
                        if ( $hideall || !in_methods_array($chosen_shipping_id, $method_ids) ){

                            unset( $fields[$fieldset][$fieldkey] );

                        }
                    }
                }
            }
        }
    }
  
    return $fields;
}

/**
*  Вывести поля для метода доставки, если он выбран в данный момент
*/
add_action('woocommerce_after_shipping_rate', 'smf_after_shipping_rate');
function smf_after_shipping_rate( $method ) {
    $chosen_methods = WC()->session->get( 'chosen_shipping_methods' );
    $chosen_shipping_id = $chosen_methods[0];

    $smf_fields = get_shipping_method_fields();
    if ( !empty( $smf_fields ) ){

        // это выбранный метод доставки?
        if ( strpos($chosen_shipping_id, $method->id) !== FALSE ){
          
            $checkout = WC()->checkout;
            foreach ($smf_fields as $fieldset => $fieldlist) {
                $allfields = $checkout->get_checkout_fields( $fieldset );
                $fieldkeys = array_keys($fieldlist);
                foreach ( $allfields as $fieldkey => $field ) {
                    $method_ids = $smf_fields[$fieldset][$fieldkey];
                    if (
                            in_array($fieldkey, $fieldkeys) &&
                            in_methods_array($chosen_shipping_id, $method_ids)
                       )
                    {
                        woocommerce_form_field( $fieldkey, $field, $checkout->get_value( $fieldkey ) );
                    }
                }
              
            }
        }
    }
}

Добрый день!

Можно ли сделать также как с выбором доставки следующее?

1. Создал новые дефолтные поля woocommerce_default_address_fields. (Поля которые изначально были пришлось создать повторно, так как приоритет отображение на странице не менялся).
2. Создал input type = "radio" с Типом плательщика.
3. Необходимо сделать так, чтобы для каждого "Типа плательщика" отображались свои поля.


Подскажите пожалуйста как можно реализовать без jQuery.

Ниже woocommerce_default_address_fields , которые я добавил, первое поле - радио кнопки при выборе, которых хотелось бы отображать определенные поля.

Код:
    // Hook in
add_filter( 'woocommerce_default_address_fields' , 'custom_override_checkout_fields' );

// Our hooked in function - $fields is passed via the filter!
function custom_override_checkout_fields( $fields ) {

    $fields = array (
    'payer_type' =>
        array(
        'label'     => __('Тип плательщика:', 'woocommerce'),
        'placeholder'   => _x('Payer Type', 'placeholder', 'woocommerce'), 
        'required'  => true,
        'class'     => array('form-row-wide'),
        'clear'     => true,
        'type'      => 'radio',
        'options'   => array('Для себя (физическое лицо)', 'Для органиции (юридическое лицо)'),
        'priority'     => 10,
         ),
         'company'    => array(
                'label'        => __( 'Company name', 'woocommerce' ),
                'class'        => array( 'form-row-wide' ),
                'autocomplete' => 'organization',
                'priority'     => 30,
                'required'     => true,
            ),
         'inn'  => array(
                'label'        => __( 'ИНН:', 'woocommerce' ),
                'placeholder'  => 'Введите ваш ИНН',
                'required'     => true,
                'class'        => array( 'form-row-first' ),
                'autocomplete' => 'inn-number',
                'priority'     => 10,
            ),
         'kpp'  => array(
                'label'        => __( 'КПП:', 'woocommerce' ),
                'placeholder'  => 'Введите ваш КПП',
                'required'     => true,
                'class'        => array( 'form-row-last' ),
                'autocomplete' => 'kpp-number',
                'priority'     => 10,
            ),
        'legal_address'  => array(
                'label'        => __( 'Юридический адрес:', 'woocommerce' ),
                'placeholder'  => 'Введите ваш Юридический адрес',
                'required'     => true,
                'class'        => array( 'form-row-wide' ),
                'autocomplete' => 'legal-address',
                'priority'     => 10,
            ),
         'actual_address'  => array(
                'label'        => __( 'Фактический адрес:', 'woocommerce' ),
                'placeholder'  => 'Введите ваш Фактический адрес',
                'required'     => true,
                'class'        => array( 'form-row-wide' ),
                'autocomplete' => 'actual-address',
                'priority'     => 10,
            ),
        'сhecking_account'  => array(
                'label'        => __( 'Расчетный счет:', 'woocommerce' ),
                'placeholder'  => 'Введите номер Расчетного счета',
                'required'     => true,
                'class'        => array( 'form-row-first' ),
                'autocomplete' => 'сhecking_account',
                'priority'     => 10,
            ),
        'bik_number'  => array(
                'label'        => __( 'БИК:', 'woocommerce' ),
                'placeholder'  => 'Введите БИК',
                'required'     => true,
                'class'        => array( 'form-row-last' ),
                'autocomplete' => 'bik_number',
                'priority'     => 10,
            ),
         'last_name'  => array(
                'label'        => __( 'Last name', 'woocommerce' ),
                'required'     => true,
                'class'        => array( 'form-row-first' ),
                'autocomplete' => 'family-name',
                'priority'     => 10,
            ),
         'first_name' => array(
                'label'        => __( 'First name', 'woocommerce' ),
                'required'     => true,
                'class'        => array( 'form-row-last' ),
                'autocomplete' => 'given-name',
                'priority'     => 20,
            ),
         'patronymic_name' => array(
                'label'        => __( 'Отчество', 'woocommerce' ),
                'required'     => false,
                'class'        => array( 'form-row-first' ),
                'autocomplete' => 'patronymic-name',
                'priority'     => 20,
            ),
         'position_name' => array(
                'label'        => __( 'Должность', 'woocommerce' ),
                'required'     => false,
                'class'        => array( 'form-row-last' ),
                'autocomplete' => 'position-name',
                'priority'     => 20,
            ),
         'postcode'    => array(
                'label'        => __( 'Postcode / ZIP', 'woocommerce' ),
                'required'     => true,
                'class'        => array( 'form-row-wide', 'address-field' ),
                'validate'     => array( 'billing-postcode' ),
                'autocomplete' => 'postal-code',
                'priority'     => 90,
            ),
         'phone'    => array(
                'label'        => __( 'Phone', 'woocommerce' ),
                'required'     => 'required' === get_option( 'woocommerce_checkout_phone_field', 'required' ),
                'type'         => 'tel',
                'class'        => array( 'form-row-first' ),
                'validate'     => array( 'phone' ),
                'autocomplete' => 'tel',
                'priority'     => 100,
            ),
        'email'     => array(
                'label'        => __( 'Email address', 'woocommerce' ),
                'required'     => true,
                'type'         => 'email',
                'class'        => array( 'form-row-last' ),
                'validate'     => array( 'email' ),
                'autocomplete' => 'no' === get_option( 'woocommerce_registration_generate_username' ) ? 'email' : 'email username',
                'priority'     => 110,
            )
    );
    return $fields;
}
 

Markiz

Новичок
Привет! Коллеги, подскажите как решить этот вопрос на текущей версии Woo?! (скрывать поле "адрес доставки" при, если человек выбрал "самовывоз") Все перепробовал, ничего не помогает. Вот сайт Сайт
 

IanAnt

Новичок
Подскажите есть ли модули по типу Быстрый заказ (купить через простую форму) , вводить только имя и номер телефона?
 

baklan

Новичок
Помогите, пожалуйста, с кодом.
В оформлении заказа у меня используется 2 вида доставки и для каждого нужно выводить поле с адресом
В коде от rred , выводится только одно поле :
PHP:
/**
* Настройка привязки полей к методам доставки.
*
* Функция возвращает массив полей заказа, которые актуальны
* только для указанных методов доставки и неприменимы для других методов.
*
* Указанные в массиве поля не будут отображаться в стандартных блоках оплаты и доставки.
* Вместо этого они будут выведены после наименования метода доставки
* и только когда он выбран.
*
* Если к определённому виду доставки привязано обязательное поле, но
* выбрана другая доставка, проблем с валидацией не будет, поскольку
* в этом случае поле исключается из обрабатываемых полей стандартным способом.
*
* Массив двумерный: поля сгруппированы по блокам, в соответствии с документацией
* https://docs.woocommerce.com/document/tutorial-customising-checkout-fields-using-actions-and-filters/#section-2
*
* Например, как сделать, чтобы поля адреса были применимы
* только к методу доставки "Единая ставка":
*
       return array(
         'billing' => array(
             'billing_address_1' => array( 'flat_rate' ),
             'billing_address_2' => array( 'flat_rate' )
         )
       );
*/
function get_shipping_method_fields() {
    return array(
        'billing' => array(
            'billing_address_1' => array( 'flat_rate' ),
            'billing_address_2' => array( 'flat_rate' ),
            'billing_postcode' => array( 'local_pickup' ),
        )
    );
}
/**
* Проверяет наличие метода доставки в формате типа 'flat_rate:3'
* в массиве методов доставки (method_id - в формате типа 'flat_rate' )
*
* @param type $chosen_shipping
* @param type $methods
* @return type
*/
function in_methods_array($chosen_shipping_id, $method_ids)
{
    $found = FALSE;
    $i = 0;
    $count = count($method_ids);
    while ( !$found && ( $i < $count ) ){
        $method_id = $method_ids[$i];
        $found = ( strpos($chosen_shipping_id, $method_id) !== FALSE );
        $i++;
    }
    return $found;
}

/**
* Скрыть в корзине и блоках оплаты и доставки поля,
* которые имеют привязку к методам доставки.
* Установленная переменная используется в фильтре woocommerce_checkout_fields
*/
add_action('woocommerce_before_cart_totals',  'smf_before_checkout_form');
add_action('woocommerce_before_checkout_form',  'smf_before_checkout_form');
function smf_before_checkout_form(){
       set_query_var( 'smf_hide_fields', TRUE );
}
add_action('woocommerce_after_checkout_form',  'smf_after_checkout_form');
add_action('woocommerce_after_cart_totals',  'smf_after_checkout_form');
function smf_after_checkout_form(){
       set_query_var( 'smf_hide_fields', FALSE );
}

/**
* Отключить неприменимые к текущему методу доставки поля.
* Или отключить всё поля, привязанные к методам доставки,
* если идёт вывод checkout_form
*/
add_filter('woocommerce_checkout_fields', 'smf_remove_checkout_fields');
function smf_remove_checkout_fields($fields) {
    $smf_fields = get_shipping_method_fields();
    if ( !empty( $smf_fields ) ){
        $hideall = get_query_var('smf_hide_fields') === TRUE;
        $chosen_methods = WC()->session->get( 'chosen_shipping_methods' );
        $chosen_shipping_id = $chosen_methods[0];
        foreach ( $fields as $fieldset => $fieldlist ) {
            if ( key_exists( $fieldset, $smf_fields ) ) {
                foreach ( $fieldlist as $fieldkey => $field ) {
                    if ( key_exists($fieldkey, $smf_fields[$fieldset] ) ){

                        $method_ids = $smf_fields[$fieldset][$fieldkey];
                        if ( $hideall || !in_methods_array($chosen_shipping_id, $method_ids) ){

                            unset( $fields[$fieldset][$fieldkey] );

                        }
                    }
                }
            }
        }
    }
  
    return $fields;
}

/**
*  Вывести поля для метода доставки, если он выбран в данный момент
*/
add_action('woocommerce_after_shipping_rate', 'smf_after_shipping_rate');
function smf_after_shipping_rate( $method ) {
    $chosen_methods = WC()->session->get( 'chosen_shipping_methods' );
    $chosen_shipping_id = $chosen_methods[0];

    $smf_fields = get_shipping_method_fields();
    if ( !empty( $smf_fields ) ){

        // это выбранный метод доставки?
        if ( strpos($chosen_shipping_id, $method->id) !== FALSE ){
          
            $checkout = WC()->checkout;
            foreach ($smf_fields as $fieldset => $fieldlist) {
                $allfields = $checkout->get_checkout_fields( $fieldset );
                $fieldkeys = array_keys($fieldlist);
                foreach ( $allfields as $fieldkey => $field ) {
                    $method_ids = $smf_fields[$fieldset][$fieldkey];
                    if (
                            in_array($fieldkey, $fieldkeys) &&
                            in_methods_array($chosen_shipping_id, $method_ids)
                       )
                    {
                        woocommerce_form_field( $fieldkey, $field, $checkout->get_value( $fieldkey ) );
                    }
                }
              
            }
        }
    }
}

Каким образом нужно доработать код, чтобы он срабатывал на 2 вида доставки?
Что-то типа этого отдаёт приоритет нижней строчке:

PHP:
       return array(

         'billing' => array(

             'billing_address_1' => array( 'flat_rate' ),

             'billing_address_1' => array( 'flat_rate2' )

         )

       );
 

marr

Специалист
Местный
Помогите, пожалуйста, с кодом.
В оформлении заказа у меня используется 2 вида доставки и для каждого нужно выводить поле с адресом
Надо разбираться, что там у вас настроено. Если помощь нужна - пишите в личку
 

baklan

Новичок
Нашёл ответ на свой вопрос. Решение банальное, но для незнающего простимо. Перечисляем адреса через запятую:
PHP:
return array(
    'billing' => array(
    'billing_address_1' => array( 'flat_rate', 'flat_rate2' )
   )
);
 

rutronix

Новичок
Доброго времени суток. Есть следующая задача - реализовать отображение выпадающего меню (выбора нужного пункта выдачи, плагин Local Pickup Plus) на странице Shopping Cart, при выборе способа доставки "самовывоз из пункта выдачи".
Т.е. выбрали самовывоз из пункта выдачи - тут же появилось выпадающее меню с адресами - выбрали адрес - перешли к выбору способа оплаты.

Всего имеем 2 способа доставки. Реализация через клик по "возможен самовывоз, кликните здесь", который только на странице оплаты, не подходит.

Заранее благодарю за ответы.
 
Сверху Снизу