#sql #wordpress #add-filter
#sql #wordpress #добавить-фильтр
Вопрос:
Я пытаюсь отредактировать a 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, amp;$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 );
Комментарии:
1. Я предполагаю, что вы пытаетесь изменить SQL более чем одного запроса. Можете ли вы поделиться кодом фильтра? Это основной запрос или вторичный запрос, который вы пытаетесь изменить?
2. Привет, это единственный запрос, выполняемый на странице, по сути, это страница поиска с постоянной ссылкой
/event-search/
, которая отредактирует мой вопрос со всемиadd_filter
функциями.3. Фильтры влияют на все ваши
WP_Query
запросы, кромеget_posts()
оболочек, где фильтры подавлены.
Ответ №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) Другим способом было бы использовать add 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() amp;amp; is_main_query() )
{
// ...
}
или
if( ! is_admin() amp;amp; $query->is_main_query() )
{
// ...
}
если вы используете pre_get_posts
перехват, где $query
находится входной аргумент.
iv) Другим вариантом было бы создать новый класс, который расширяет WP_Query
и содержит все нужные фильтры:
class My_Search_Query extends WP_Query
{
// ...
}
где вы используете
$query = new My_Search_Query( $args );
для выполнения запроса.
Комментарии:
1. Отлично! Это избавило от ошибки SQL, как ни странно, это нарушило разбивку страницы на страницы, странно!
2. Это здорово. Не изменяется ли подкачка в SQL-запросе?
3. Ах, отсортировал его, изменив главную страницу на статическую страницу в настройках 🙂