Почему возникает PHP Notice при запросе get_the_terms?

Ссылка скопирована
1 ответ

Написал простой плагинчик для ВП, который получает метаполя от категории товара WC.
Вижу в логах полно сообщений:

PHP Notice:  Trying to get property 'ID' of non-object in myfile.php on line 17

PHP Notice: Trying to get property 'ID' of non-object in myfile.php on line 17

Код

function myfun( $price ) { global $post;     $terms = get_the_terms( $post->ID,  'product_cat' ); // <-17 строка 	if( $terms ){ //... }          return $price;      }      add_filter( 'woocommerce_get_price_html', 'myfun' );

function myfun( $price ) { global $post; $terms = get_the_terms( $post->ID, 'product_cat' ); // <-17 строка if( $terms ){ //... } return $price; } add_filter( 'woocommerce_get_price_html', 'myfun' );

Не пойму что не так, как избавится от этих нотисов?

Дополнительно:

А точно там ид с больших букв?

  • Дмитрий, Да. Пример употребления
  • Видимо в некоторых случаях global $post пустой
  • Видимо в некоторых случаях global $post пустой

    Точнее, $post в каких то случаях не объект, может не инициализирована, а может там массив или еще что-то.

  • Vitsliputsli, думаю что проверка на объект решит проблему)
  • Maksym Davydchuk,

    думаю что проверка на объект решит проблему)

    Не столько решит, сколько скроет.
    Вопрос несколько шире, чем просто избавление от ошибок в логах. $post (в моём случае) всегда должен быть объектом. А почему не всегда и когда это происходит - вот это не понятно. Или же я чего-то не понимаю как работает фильтр и вообще код.

  • Ответы:

    if (empty($_POST)) {
    $post = (object) json_decode(file_get_contents('php://input'), true)['params'] ?? (object) [];
    }
    Если запрос сделан с помощью axios, то приходит в php://input
    ЗЫ: Я не в курсе как ВП валидирует запросы. Из того что я предложил придёт то, что было отправлено.

    • Спасибо, но вопрос немного не в том, что бы просто скрыть (это я в принципе уже сделал, но это). Вопрос больше по ВП.
      См мой коммент к вопросу https://qna.habr.com/q/1286704#clarification_1749300
    • Refguser, так и мой ответ не про, чтобы скрыть. Он про то, как получить данные.
      ВП ожидает, что они будут в массиве $_POST. Их там нет, потому что они пришли в php://input
    Нужно решить такую задачу?

    Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.

    Заказать помощь
    Лучший ответ
    1
    Web-разработка Ответ

    Notice появляется потому, что в момент срабатывания фильтра woocommerce_get_price_html глобальная переменная $post не всегда является объектом товара. Этот фильтр может вызываться в админке, AJAX-запросах, виджетах, блоках, REST, мини-корзине или при расчётах, где глобальный $post не установлен.

    В WooCommerce в таких фильтрах лучше не брать товар через global $post. У фильтра woocommerce_get_price_html есть второй аргумент — объект продукта. Его и нужно использовать.

    add_filter('woocommerce_get_price_html', 'myfun', 10, 2);
     
    function myfun($price, $product) {
        if (!$product instanceof WC_Product) {
            return $price;
        }
     
        $product_id = $product->get_id();
        $terms = get_the_terms($product_id, 'product_cat');
     
        if (is_wp_error($terms) || empty($terms)) {
            return $price;
        }
     
        foreach ($terms as $term) {
            // Ваша логика по категории товара.
        }
     
        return $price;
    }

    add_filter('woocommerce_get_price_html', 'myfun', 10, 2); function myfun($price, $product) { if (!$product instanceof WC_Product) { return $price; } $product_id = $product->get_id(); $terms = get_the_terms($product_id, 'product_cat'); if (is_wp_error($terms) || empty($terms)) { return $price; } foreach ($terms as $term) { // Ваша логика по категории товара. } return $price; }

    Такой код не просто скрывает notice, а убирает неправильную зависимость от глобального состояния. global $post допустим в обычном шаблоне внутри Loop, но в фильтрах WooCommerce это ненадёжно.

    Если нужно проверить конкретную категорию, можно проще:

    if (has_term('sale-category', 'product_cat', $product->get_id())) {
        // Логика для товаров из категории.
    }

    if (has_term('sale-category', 'product_cat', $product->get_id())) { // Логика для товаров из категории. }

    Ещё один нюанс: get_the_terms() может вернуть false или WP_Error, поэтому проверка должна учитывать оба случая. Иначе вместо одного notice можно получить другой при переборе результата.

    Итог: причина не в регистре ID, а в том, что $post не гарантирован в этом фильтре. Используйте аргумент $product и задайте accepted_args равным 2.

    Другие ответы (0)

    Пока нет других ответов. Будьте первым, кто поможет автору.

    Ответить на вопрос

    комментарий

    Ваш адрес email не будет опубликован. Обязательные поля помечены *

    Вам также может быть интересно