Почему возникает PHP Notice при запросе get_the_terms?
Написал простой плагинчик для ВП, который получает метаполя от категории товара 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 пустой
Точнее, $post в каких то случаях не объект, может не инициализирована, а может там массив или еще что-то.
думаю что проверка на объект решит проблему)
Не столько решит, сколько скроет.
Вопрос несколько шире, чем просто избавление от ошибок в логах. $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
Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.
Пока нет других ответов. Будьте первым, кто поможет автору.
Ответить на вопрос
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; }
Такой код не просто скрывает notice, а убирает неправильную зависимость от глобального состояния.
global $postдопустим в обычном шаблоне внутри Loop, но в фильтрах WooCommerce это ненадёжно.Если нужно проверить конкретную категорию, можно проще:
if (has_term('sale-category', 'product_cat', $product->get_id())) { // Логика для товаров из категории. }
Ещё один нюанс:
get_the_terms()может вернутьfalseилиWP_Error, поэтому проверка должна учитывать оба случая. Иначе вместо одного notice можно получить другой при переборе результата.Итог: причина не в регистре
ID, а в том, что$postне гарантирован в этом фильтре. Используйте аргумент$productи задайтеaccepted_argsравным 2.