Существует ли что-то вроде 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().
Ian Dunn
Только что столкнулся с той же проблемой и написал простую функцию 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-запросы, и она сработала идеально.
Philip
Если вам нужно проверить после срабатывания 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
Думаю, это не сработает, если у вас не включены красивые постоянные ссылки.
websupporter
Да, это требует красивых постоянных ссылок... но кто же их не хочет использовать?! Мне кажется, это самый надежный способ. Все остальные решения выглядят изящно, но если вы хотите, чтобы ваш код работал в будущих версиях WP... этот способ кажется мне самым безопасным!!
Antony Gibbs
В 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/