Вопрос или проблема
По видимому, по каким-то нелогичным причинам разработчики решили, что единственный способ получить публикации на всех языках — это добавить supress_filters=true
в WP_Query (вместо того, чтобы, скажем, иметь опцию language_code=all
).
В любом случае, я нахожусь в ситуации, когда мне нужно получить публикации на всех языках, но также МОДИФИЦИРОВАТЬ WP_Query с помощью фильтров. Есть ли способ обеспечить добавление моих фильтров в запрос, даже если supress_filters
установлен на false
?
Это фильтр, который мне нужно добавить:
add_filter( 'posts_where', function($where, $wp_query) {
global $wpdb;
if($search_term = $wp_query->get( 'custom_search' )){
$search_term = $wpdb->esc_like($search_term);
$search_term = ' \'%' . $search_term . '%\'';
$where .= ' AND (' . $wpdb->posts . '.post_title LIKE ' . $search_term . ' OR ' . $wpdb->posts . '.ID LIKE ' . $search_term . ' OR ' . $wpdb->posts . '.post_name LIKE ' . $search_term . ')';
}
return $where;
}, 10, 2 );
Но он удаляется после добавления supress_filters=true
(поскольку мне нужно получить публикации на ВСЕХ языках)
Посмотрев на класс WP_Query, вы должны иметь возможность использовать pre_get_posts
, чтобы изменить запрос до того, как будут выполнены какие-либо другие фильтры, включая отключение флага suppress_filters
. Пример этого может быть таким:
/**
* Изменение WP_Queries
* @link https://wordpress.stackexchange.com/q/356950/7355
*
* @param WP_Query $query
*
* @return void
*/
function wpse356950_query_modifications( $query ) {
// Не запускать в админке
if( is_admin() ) {
return;
}
// Какое-то условие, чтобы отличить наш запрос от других запросов
if( $query->get( 'suppress_filters' ) ) {
$query->set( 'suppress_filters', false );
}
}
add_action( 'pre_get_posts', 'wpse356950_query_modifications' );
Один из способов, который я нашел, это вручную удалить фильтры, добавленные ядром WPML, вот так:
global $wpml_query_filter;
/**
* WPML выборка на всех языках
*/
remove_filter( 'posts_join', array( $wpml_query_filter, 'posts_join_filter' ), 10, 2 );
remove_filter( 'posts_where', array( $wpml_query_filter, 'posts_where_filter' ), 10, 2 );
Это подходит в моей ситуации, так как на этой конкретной странице только один WP_Query. Если у вас несколько, где нужно выбирать для конкретного языка, я рекомендую заново добавить фильтры после выполнения WP_Query.
Ответ или решение
Обход "suppress_filters" в WP_Query
Когда вы работаете с WP_Query в WordPress и вам требуется загружать посты на всех языках, вы можете столкнуться с проблемой, связанной с использованием параметра suppress_filters=true
. Использование этого параметра приводит к тому, что все фильтры, которые вы добавили, игнорируются, и это может вызывать сложности, особенно если вы хотите модифицировать результаты запроса.
Проблема
Как правило, для получения постов на всех языках с использованием WPML (WordPress Multilingual Plugin) необходимо добавить флаг suppress_filters=true
. Однако это отключает все фильтры, которые могут быть вам нужны для модификации запроса, например, фильтры поиска, которые вы добавили через add_filter()
.
Решение
Есть несколько способов обойти эту проблему:
-
Использование
pre_get_posts
для модификации запроса:
Вы можете использовать хукpre_get_posts
, чтобы модифицировать WP_Query перед выполнением запроса. Например, если в вашем контекстеsuppress_filters
установлен вtrue
, вы можете изменить его наfalse
. Вот пример кода:/** * Модификация WP_Query * @link https://wordpress.stackexchange.com/q/356950/7355 * * @param WP_Query $query * * @return void */ function wpse356950_query_modifications( $query ) { // Не запускать в административной панели if( is_admin() ) { return; } // Проверка условия для нашего запроса if( $query->get( 'suppress_filters' ) ) { $query->set( 'suppress_filters', false ); } } add_action( 'pre_get_posts', 'wpse356950_query_modifications' );
Этот код позволит переопределить значение
suppress_filters
для вашего WP_Query, сохранив при этом примененные фильтры. -
Удаление фильтров WPML и их восстановление:
Если вы используете WPML, возможно, вам потребуется удалить некоторые фильтры, добавленные плагином, чтобы ваши собственные фильтры работали корректно. Например:global $wpml_query_filter; // Удаление фильтров WPML remove_filter( 'posts_join', array( $wpml_query_filter, 'posts_join_filter' ), 10, 2 ); remove_filter( 'posts_where', array( $wpml_query_filter, 'posts_where_filter' ), 10, 2 );
Это может быть вполне приемлемым решением, если на странице есть лишь один WP_Query. В случае наличия нескольких запросов, вам необходимо будет повторно добавить фильтры после выполнения основного запроса.
Заключение
Использование параметра suppress_filters
в WP_Query действительно может стать препятствием для модификации запросов через фильтры. Тем не менее, с помощью хука pre_get_posts
и правильного управления фильтрами вы можете добиться желаемых результатов, получая посты на всех языках и сохраняя функциональность фильтров. Это позволит вашему коду быть более гибким и адаптированным под требования вашего проекта.