Функция add_filter не работает должным образом

Я пытаюсь отредактировать wp_query в WordPress с помощью add_filterфункции. Когда я var_dump делаю свой запрос request, он выводит SQL, как и ожидалось.

Однако при запуске он возвращает ошибку с другим запросом! Кто-нибудь знает, почему запрос может измениться, и измениться так сильно!

Запрос от request var_dump (как и ожидалось):

SELECT SQL_CALC_FOUND_ROWS  wp_posts.*, 
    ( 3959 * acos(
         cos( radians(52.486243) ) 
         * cos( radians( lat ) ) 
         * cos( radians( lng ) - radians(-1.890401) ) 
         + sin( radians(52.486243) ) 
         * sin( radians( lat ) ) 
         ) ) 
     AS distance , lat AS  latitude , lng AS longitude 
FROM wp_posts  
INNER JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id) 
INNER JOIN wp_postmeta ON (wp_posts.ID = wp_postmeta.post_id)
INNER JOIN wp_postmeta AS mt1 ON (wp_posts.ID = mt1.post_id) 
INNER JOIN lat_lng_post ON wp_posts.ID = lat_lng_post.post_id 
WHERE 1=1  
AND ( wp_term_relationships.term_taxonomy_id IN (2) ) 
AND wp_posts.post_type = 'event' 
AND ((wp_posts.post_status = 'publish')) 
AND ( (wp_postmeta.meta_key LIKE 'date_%_start-date' AND CAST(wp_postmeta.meta_value AS SIGNED) <= '20140704')
AND  (mt1.meta_key LIKE 'date_%_end-date' AND CAST(mt1.meta_value AS SIGNED) >= '20140627') ) 
AND lat_lng_post.lat = lat 
AND lat_lng_post.lng = lng 
AND substr(wp_postmeta.meta_key, 1, 6) = substr(mt1.meta_key, 1, 6)  
GROUP BY wp_posts.ID 
HAVING distance <= 20 
ORDER BY distance ASC 
LIMIT 0, 10

И это запрос, который показывает ниже ошибку [Unknown column 'lat' in 'field list'] (не ожидается):

SELECT wp_posts.*, 
    ( 3959 * acos( 
        cos( radians(52.486243) ) 
        * cos( radians( lat ) ) 
        * cos( radians( lng ) - radians(-1.890401) ) 
        + sin( radians(52.486243) ) 
        * sin( radians( lat ) ) 
     ) ) AS distance , lat AS latitude , lng AS longitude 
FROM wp_posts 
WHERE 1=1 
AND wp_posts.post_type = 'acf-field' 
AND ((wp_posts.post_status = 'publish')) 
AND wp_posts.post_name = 'field_535e6b9ffe3da' 
AND lat_lng_post.lat = lat 
AND lat_lng_post.lng = lng 
GROUP BY wp_posts.ID 
HAVING distance <= 20 
ORDER BY distance ASC 
LIMIT 0, 1

ПРИМЕЧАНИЕ

У меня есть пользовательская таблица с именем lat_lng_post, в которой есть три столбца: post_id, lat, lng для хранения данных о местоположении для каждого события (пользовательский тип сообщения).

ИЗМЕНИТЬ все функции add_filter, используемые в запросе:

function distance_query($distance) {

    $lat = $_SESSION['search']['lat'];
    $lng = $_SESSION['search']['long'];


    $distance .= ", 
    ( 3959 * acos(
         cos( radians(".$lat.") ) 
         * cos( radians( lat ) ) 
         * cos( radians( lng ) - radians(".$lng.") ) 
         + sin( radians(".$lat.") ) 
         * sin( radians( lat ) ) 
         ) ) 
     AS distance , lat AS  latitude , lng AS longitude";
    return $distance;
}
add_filter('posts_fields', 'distance_query');



// add lat_lng_post table inner join
function lat_lng_join($join) {
    $join = str_replace('(wp_posts.ID = mt1.post_id)', '(wp_posts.ID = mt1.post_id) INNER JOIN lat_lng_post ON wp_posts.ID = lat_lng_post.post_id', $join);
    return $join;
}
add_filter('posts_join', 'lat_lng_join');


// set lat lng definition
function lat_lng_define($define) {
    $define .= ' AND lat_lng_post.lat = lat AND lat_lng_post.lng = lng';
    return $define;
}
add_filter('posts_where', 'lat_lng_define');


// HAVING distance less than user distance
function having_distance($having) {
    $radius = $_SESSION['search']['distance'];
    $having = 'wp_posts.ID HAVING distance <= '.$radius.'';
    return $having;
}
add_filter('posts_groupby', 'having_distance');

// if sorting by distance
function sort_distance($sortdistance) {
    $sortdistance = 'distance ASC';
    return $sortdistance;
}
if( $_SESSION['search']['sort-by'] == 'distance' ) :
    add_filter('posts_orderby', 'sort_distance');
endif;


function add_additional_where_condition($where) {
    $where .= " AND substr(wp_postmeta.meta_key, 1, 6) = substr(mt1.meta_key, 1, 6) ";
    return $where;
}

// fix for setting the date to search field
function date_to( $to ) {
    $to = str_replace("mt1.meta_key = 'date_%_end-date'", "mt1.meta_key LIKE 'date_%_end-date'", $to);
    return $to;
}

// fix for setting the date from search field   
function date_from( $from ) {
    $from = str_replace("meta_key = 'date_%_start-date'", "meta_key LIKE 'date_%_start-date'", $from);
    return $from;
}

// fix for ordering by date
function order_date( $like ) {
    $like = str_replace("mt2.meta_key = 'date_%_end-date'", "mt2.meta_key LIKE 'date_%_end-date'", $like);
    return $like;
}

// fix for searching by LIKE post title, requires all characters to match 
function title_filter( $where, &$wp_query ) {
    global $wpdb;
    if ( $search_term = $wp_query->get( 'title_like' ) ) {
        $where .= ' AND ' . $wpdb->posts . '.post_title LIKE \'%' . esc_sql( like_escape( $search_term ) ) . '%\'';
    }
    return $where;
}

Кроме того, это сам wp_query, к которому добавляются эти функции:

// add query for title
    add_filter( 'posts_where', 'title_filter', 10, 2 );

// dates to and from logic
    add_filter('posts_where', 'date_from');
    add_filter('posts_where', 'date_to');
    add_filter('posts_where', 'order_date');
    add_filter('posts_where', 'add_additional_where_condition');


// get date inputs from search
    $date1 = str_replace('/', '-', $_SESSION['search']['from']);
    $when = date("Ymd", strtotime($date1));

    $date2 = str_replace('/', '-', $_SESSION['search']['to']);
    $when2 = date("Ymd", strtotime($date2));

    $year = date('Y');




// Declare the query arguments 
    if ( get_query_var('paged') ) { 
        $paged = get_query_var('paged'); 
    } else if ( get_query_var('page') ) {
        $paged = get_query_var('page'); 
    } else {
        $paged = 1; 
    }

// make keywords an array
    $keywordString = $_SESSION['search']['keyword'];
    $keywords = explode(', ', $keywordString);

    $taxQuery = array(
        'relation' => 'AND',
        array (
            'taxonomy' => 'main-cat',
            'field' => 'slug',
            'terms' => $_SESSION['search']['cat']
        )
    );

    if( $_SESSION['search']['keyword'] != '' ) {
        $taxQuery[] = array(
            'taxonomy' => 'sub-cat',
            'field' => 'name',
            'terms' => $keywords
        );
    }

    $args = array(
        // general
        'post_type' => 'event',
        'post_status' => 'publish',
        'posts_per_page' => 10,
        'paged' => $paged,
        'cache_results' => false,
        'update_post_meta_cache' => false,
        'update_post_term_cache' => false,

        'meta_key' => $_SESSION['search']['sort-key'],
        'orderby' => $_SESSION['search']['sort-by'],
        'order' => 'ASC',

        // category filter
        'tax_query' => $taxQuery,

        // date filter

        'meta_query' => array(
            'relation' => 'AND',
            array(
                'key' => 'date_%_start-date',
                'value' => $when2,
                'compare' => '<=',
                'type' => 'NUMERIC'
            ),
            array (
                'key' => 'date_%_end-date',
                'value' => $when,
                'compare' => '>=',
                'type' => 'NUMERIC'
            )

        )
    );


    $temp = $wp_query;
    $wp_query = null;
    $wp_query = new WP_Query( $args );

person lukeseager    schedule 27.06.2014    source источник
comment
Я предполагаю, что вы пытаетесь изменить SQL более чем одного запроса. Не поделитесь кодом фильтра? Это основной или дополнительный запрос, который вы пытаетесь изменить?   -  person birgire    schedule 30.06.2014
comment
Привет, это единственный запрос, выполняемый на странице, по сути, это страница поиска с постоянной ссылкой /event-search/, которая отредактирует мой вопрос со всеми функциями add_filter.   -  person lukeseager    schedule 30.06.2014
comment
Фильтры влияют на все ваши запросы WP_Query, кроме оболочек get_posts(), где фильтры подавляются.   -  person birgire    schedule 30.06.2014


Ответы (1)


Похоже, вы пытаетесь настроить posts_* фильтры для дополнительного запроса, но затем забываете удалить фильтры, поэтому они влияют на другие запросы, которые выполняются позже.

i) Вы можете удалить фильтр с помощью функции remove_filter(). Вот пример:

// Add some filter:
add_filter( 'some_filter', 'some_filter_callback', $priority );

// Run a secondary query:
$wp_query = new WP_Query( $args );

// Remove the previous filter:
remove_filter( 'some_filter', 'some_filter_callback', $priority );

где должен совпадать приоритет фильтра.

ii) Другой способ — добавить remove_filter() внутрь функции some_filter_callback(). Например:

add_filter( 'some_filter', 'some_filter_callback' );
$wp_query = new WP_Query( $args );

куда

some_filter_callback( $string )
{
    // Remove the current filter:
    remove_filter( current_filter(), __FUNCTION__ );

    // Some modifications to the input:
    // ...

    // Output:
    return $string;
}

Это гарантирует, что ваш фильтр будет работать только один раз.

iii) Если вы пытаетесь изменить основной запрос, вы можете ограничить фильтр следующим образом:

if( ! is_admin() && is_main_query() )
{
     // ...
}

or

if( ! is_admin() && $query->is_main_query() )
{
     // ...
}

если вы используете хук pre_get_posts, где $query — входной аргумент.

iv) Другим вариантом может быть создание нового класса, который расширяет WP_Query и содержит все необходимые фильтры:

class My_Search_Query extends WP_Query
{
   // ...
}

где вы используете

$query = new My_Search_Query( $args );

чтобы выполнить запрос.

person birgire    schedule 30.06.2014
comment
Здорово! Это избавило от ошибки SQL, но, как ни странно, это нарушило разбиение на страницы для страницы, странно! - person lukeseager; 01.07.2014
comment
Замечательно. Пейджинг не меняется в SQL-запросе? - person birgire; 01.07.2014
comment
А, разобрался, изменив в настройках главную страницу на статичную :) - person lukeseager; 02.07.2014