действие woocommerce_update_product — срабатывает только один раз для каждого обновления продукта

Какой обходной путь существует для запуска действия woocommerce_update_product только один раз?

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

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

Единственный обходной путь, который я нашел до сих пор, — это добавить действие и удалить его напрямую в хуке:

add_action('woocommerce_update_product', 'my_product_update', 10, 2);
function my_product_update($product_id, $product){
    remove_action('woocommerce_update_product');
    // We'll get here only once!
}

Однако это ломается при попытке выполнить массовое редактирование, поэтому хук срабатывает только для первого продукта (потому что впоследствии он удаляется!).

Какой еще способ обойти эту проблему?

Спасибо!


person OhMad    schedule 30.12.2019    source источник
comment
как насчет добавления пользовательских метаданных в обновленные продукты? после обновления всех продуктов удалите его.   -  person Ali Qorbani    schedule 30.12.2019
comment
Как узнать, когда нужно удалить пользовательские метаданные?   -  person OhMad    schedule 30.12.2019


Ответы (2)


Возможно, поможет использование WordPress Transient.

add_action('woocommerce_update_product', 'my_product_update', 10, 2);
function my_product_update($product_id, $product) {

    $updating_product_id = 'update_product_' . $product_id;
    if ( false === ( $updating_product = get_transient( $updating_product_id ) ) ) {
        // We'll get here only once! within 2 seconds for each product id;
        // run your code here!
        set_transient( $updating_product_id , $product_id, 2 ); // change 2 seconds if not enough
    }
}
person Reigel    schedule 30.12.2019
comment
Спасибо за ответ. Единственное, о чем я беспокоюсь, это то, что фактические обновления приходят быстрее, чем указанное время. - person OhMad; 30.12.2019
comment
это действительно произойдет? например, обновлять один продукт более одного раза в 2 секунды? это возможно, но я не думаю, что это было бы практически. - person Reigel; 31.12.2019
comment
Да, это хороший момент. Там это могло быть, но это, вероятно, маловероятно (и, возможно, его стоит игнорировать). Спасибо, что подняли это! - person OhMad; 01.01.2020
comment
вы даже можете установить его на 1 секунду... Это должно работать, если вы поместите set_transient в самую последнюю строку для запуска... как сейчас... - person Reigel; 01.01.2020
comment
Да, я сделал это. Еще один вопрос по коду: почему оператор if не говорит просто: if (!get_transient($updating_product))? Для меня это работает нормально. - person OhMad; 01.01.2020
comment
в зависимости от использования. Я отредактировал свой ответ, чтобы сделать его более понятным. но да, ваш if тоже должен работать... - person Reigel; 01.01.2020
comment
Спасибо за вашу помощь, я ценю это! - person OhMad; 01.01.2020
comment
Это действительно помогло мне отправлять push-уведомления о добавлениях и обновлениях продукта с помощью Firebase Cloud Messaging в приложение Flutter, потому что хук woocommerce_update_product запускается дважды и отправляется два уведомления. - person Mycodingproject; 10.09.2020

Более простым решением было бы установить переменную $_POST и проверить ее в начале функции.

add_action( 'woocommerce_update_product', 'my_action', 10, 1 );
function my_action(){
   if( isset($_POST['action_performed']) ){
      //Prevent running the action twice
      return;
    }
   
   // do you stuff here

   $_POST['action_performed'] = true;
}
person Jahanzeb Khan    schedule 31.05.2021