Существует ли что-то вроде is_rest()
Я начинаю работать с REST API. Если я не ошибаюсь, хук действия init
также выполняется при REST API запросе. Теперь мне нужно выполнять некоторый код только тогда, когда это не REST API запрос.
Я искал что-то вроде функции is_rest()
, чтобы сделать следующее:
<?php
if( ! is_rest() ) echo 'no-rest-request';
?>
Но я не смог найти ничего подобного. Существует ли is_rest()
в WordPress?

Это верное замечание от @Milo, константа REST_REQUEST
определяется как true
внутри функции rest_api_loaded()
, если $GLOBALS['wp']->query_vars['rest_route']
не пуста.
Она подключается к parse_request
через:
add_action( 'parse_request', 'rest_api_loaded' );
но parse_request
срабатывает позже, чем init
- Смотрите, например, Кодекс здесь.
Было предложение (от Daniel Bachhuber) в тикете #34373 относительно WP_Query::is_rest()
, но оно было отложено/отменено.

#42061 может добавить wp_is_rest_request()
или wp_doing_rest()
.

Только что столкнулся с той же проблемой и написал простую функцию is_rest
, которая позволяет проверить, является ли текущий запрос запросом к WP REST API.
<?php
if ( !function_exists( 'is_rest' ) ) {
/**
* Проверяет, является ли текущий запрос запросом к WP REST API.
*
* Случай #1: После инициализации WP_REST_Request
* Случай #2: Поддержка "простых" настроек постоянных ссылок и проверка, начинается ли `rest_route` с `/`
* Случай #3: Может случиться, что WP_Rewrite еще не инициализирован,
* поэтому делаем это (wp-settings.php)
* Случай #4: Путь URL начинается с wp-json/ (ваш REST префикс)
* Также поддерживает установки WP в подпапках
*
* @returns boolean
* @author matzeeable
*/
function is_rest() {
if (defined('REST_REQUEST') && REST_REQUEST // (#1)
|| isset($_GET['rest_route']) // (#2)
&& strpos( $_GET['rest_route'], '/', 0 ) === 0)
return true;
// (#3)
global $wp_rewrite;
if ($wp_rewrite === null) $wp_rewrite = new WP_Rewrite();
// (#4)
$rest_url = wp_parse_url( trailingslashit( rest_url( ) ) );
$current_url = wp_parse_url( add_query_arg( array( ) ) );
return strpos( $current_url['path'] ?? '/', $rest_url['path'], 0 ) === 0;
}
}
Ссылки:

Это лучшая функция для WordPress, когда-либо написанная на Stackoverflow. Мне нужно было использовать её для хука pre_get_posts
, который игнорирует REST-запросы, и она сработала идеально.

Если вам нужно проверить после срабатывания init
:
defined('REST_REQUEST') && REST_REQUEST
Если нужно проверить до init
, есть два способа:
Используйте wp_is_json_request()
(добавлено в WordPress 5.0) или попробуйте определить REST-запрос по URL. Определение URL будет отличаться в зависимости от того, используются ли ЧПУ или обычные ссылки.
WooCommerce делает это следующим образом, и это хорошее решение:
function is_rest_api_request() {
if ( empty( $_SERVER['REQUEST_URI'] ) ) {
// Вероятно, это CLI-запрос
return false;
}
$rest_prefix = trailingslashit( rest_get_url_prefix() );
$is_rest_api_request = strpos( $_SERVER['REQUEST_URI'], $rest_prefix ) !== false;
return apply_filters( 'is_rest_api_request', $is_rest_api_request );
}

Здесь есть два варианта:
- Проверить, определена ли константа
REST_REQUEST
. - Использовать хук
rest_api_init
вместо того, чтобы вешать обработчик на хукinit
.

Для решения этой проблемы я написал простую пользовательскую функцию, основанную на предположении, что если запрашиваемый URI относится к URL Rest API сайта WordPress, то это означает, что это запрос к Rest API.
Является ли конечная точка валидной или аутентифицированной, эта функция не определяет. Вопрос в следующем: является ли URL потенциальным URL Rest API?
function isRestUrl() {
$bIsRest = false;
if ( function_exists( 'rest_url' ) && !empty( $_SERVER[ 'REQUEST_URI' ] ) ) {
$sRestUrlBase = get_rest_url( get_current_blog_id(), '/' );
$sRestPath = trim( parse_url( $sRestUrlBase, PHP_URL_PATH ), '/' );
$sRequestPath = trim( $_SERVER[ 'REQUEST_URI' ], '/' );
$bIsRest = ( strpos( $sRequestPath, $sRestPath ) === 0 );
}
return $bIsRest;
}
Если ваш $_SERVER['REQUEST_URI']
не заполнен корректно, эта функция всё равно вернёт false
.
Жёсткого кодирования URL нет, поэтому если вы по какой-то причине измените базовый URL API, функция адаптируется.

Возможно, не совсем правильно, но в итоге получилось так:
if (strpos($_SERVER[ 'REQUEST_URI' ], '/wp-json/') !== false) {
// Здесь крутые API-штуки
}
Буду рад, если укажете, если это неверно. Пытаюсь сделать полезный стартер для плагина, чтобы впоследствии поделиться: https://gitlab.com/ripp.io/wordpress/plugin-starter

Думаю, это не сработает, если у вас не включены красивые постоянные ссылки.

Да, это требует красивых постоянных ссылок... но кто же их не хочет использовать?! Мне кажется, это самый надежный способ. Все остальные решения выглядят изящно, но если вы хотите, чтобы ваш код работал в будущих версиях WP... этот способ кажется мне самым безопасным!!

В WordPress 6.5 ядро предоставляет функцию wp_is_rest_endpoint
для надежного определения, является ли текущий запрос запросом к конечной точке REST.
Также есть другая функция wp_is_serving_rest_request
для проверки, действительно ли обслуживается запрос к REST API. Если вы используете её, убедитесь, что вызываете её после действия parse_request
, так как до этого она всегда будет возвращать false
.

Вы можете использовать wp_is_json_request()
следующим образом:
if ( wp_is_json_request() ) {
// выполните здесь ваши действия
}
Убедитесь, что вы установили заголовки Accepts
или Content-Type
как application/json
, иначе wp_is_json_request()
вернет false.
Дополнительная документация: https://developer.wordpress.org/reference/functions/wp_is_json_request/
