Обойти “suppress_filters” в WP Query

Вопрос или проблема

По видимому, по каким-то нелогичным причинам разработчики решили, что единственный способ получить публикации на всех языках — это добавить 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().

Решение

Есть несколько способов обойти эту проблему:

  1. Использование 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, сохранив при этом примененные фильтры.

  2. Удаление фильтров 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 и правильного управления фильтрами вы можете добиться желаемых результатов, получая посты на всех языках и сохраняя функциональность фильтров. Это позволит вашему коду быть более гибким и адаптированным под требования вашего проекта.

Оцените материал
Добавить комментарий

Капча загружается...