Custom Queries. Фильтры для изменения SQL запроса на выборку постов в wordpress.
Здравствуйте, У меня довольно сложный вопрос касающийся вордпресс и выборки записей через wp_query с использованием кастомного(произвольного) SQL запроса. Мне нужно в стандартный вывод продуктов(из woocommerce), добавить несколько своих параметров для нужной мне выборке продуктов. Требуется выбрать по произвольным полям и сортировать в определенном порядке(моем порядке, не просто asc или desc). Стандартные средства wp_query не помогают. Из вариантов вижу только полностью переписать запрос перед выборкой(что не хотелось бы делать, так как нужно будет самому получать параметры категорий, сколько выводить на страницу и прочее). И частично внедриться в sql запрос, только как это сделать не представляю. Может кто нибудь чем нибудь помочь?
Фильтры:
Фильтры на SQL запрос через wp_query
posts_request — Весь sql запрос
Пример:
add_filter('posts_request', 'post_search_request'); function post_search_request($request){ var_dump($request); // выведет запрос полностью }
posts_join — фильтр на соединение таблиц с помощью оператора join
Пример:
add_filter('posts_join', 'post_search_join'); function post_search_join($join){ var_dump($join); // выведет часть запроса по выбору/соединению таблиц базы данных с использованием оператора join }
posts_where — фильтр на параметры выборки в sql запросе wp_query
Пример:
add_filter('posts_where', 'post_search_where'); function post_search_where($where){ var_dump($where); // выведет часть запроса с условиями выборки WHERE ... }
posts_orderby — фильтр на сортировку выборки ORDER BY
Пример:
add_filter('posts_orderby', 'post_search_orderby'); function post_search_orderby($orderby){ var_dump($orderby); // выведет часть запроса указанного после оператора ORDER BY }
post_limits — фильтр на оператор LIMIT(количество выводимых записей)
Пример:
function wpcodex_filter_main_search_post_limits( $limit, $query ) { if ( ! is_admin() && $query->is_main_query() && $query->is_search() ) { return 'LIMIT 0, 25'; // будем выводить 25 записей из базы } return $limit; } add_filter( 'post_limits', 'wpcodex_filter_main_search_post_limits', 10, 2 );
posts_clauses — вернем в в виде массива параметры текущего запроса
Пример:
/** Функция выведет параметры sql для всех запросов на странице. В массиве содержаться * posts_where_paged * posts_groupby * posts_join_paged * posts_orderby * posts_distinct * post_limits * posts_fields */ function intercept_query_clauses( $pieces ) { echo '<style>#post-clauses-dump { display: block; background-color: #777; color: #fff; white-space: pre-line; }</style>'; // >>>> Inspect & Debug the Query // NEVER EVER show this to anyone other than an admin user - unless you're in your local installation if ( current_user_can( 'manage_options' ) ) { $dump = var_export( $pieces, true ); echo "<pre id='post-clauses-dump'>{$dump}</pre>"; } return $pieces; } add_filter( 'posts_clauses', 'intercept_query_clauses', 20, 1 );
posts_distinct — фильтр устраняет дубликаты в результатах поиска.
Пример:
function search_distinct() { if ( $this->allow_duplicates ) return ""; // filter has no effect return "DISTINCT"; } add_filter('posts_distinct', 'search_distinct');
posts_results — Фильтр дает возможность отфильтровать полученные результаты sql запроса
Пример:
function my_posts_results_filter( $posts ) { $filtered_posts = array(); print_r( $posts ); foreach ( $posts as $post ) { if ( false === strpos($post->post_title, 'selfie')) { // safe to add non-selfie title post to array $filtered_posts[] = $post; } } return $filtered_posts ; } add_filter( 'posts_results', 'my_posts_results_filter' );
Как выбрать нужный нам sql запрос
Что бы применить изменения(фильтры которые перечислены выше) в sql запросе, именно для нужного нам запроса, можно использовать событие «pre_get_posts«.
pre_get_posts — срабатывает перед каждым запросом WP_Query
Например:
function onwp_pre_get_posts($query) { if (is_archive()) { if (!is_admin() && $query->is_main_query() && ($query->query_vars['post_type'] == 'product')) { add_filter('posts_join', 'post_search_join'); add_filter('posts_where', 'post_search_where'); add_filter('posts_orderby', 'post_alphabetical'); } } return $query; } add_action('pre_get_posts', 'onwp_pre_get_posts');
Теперь наши 3 фильтра сработают только на странице категории, не в админки и если тип записи будет ‘product’.
Для применения событий только к нужному запросу нам возможно понадобятся другие функции для проверки. Приведу пример некоторых из них:
// простые проверки true/false $query->is_404 $query->is_admin $query->is_archive $query->is_attachment $query->is_author $query->is_category $query->is_comments_popup $query->is_comment_feed $query->is_date $query->is_day $query->is_feed $query->is_home $query->is_month $query->is_page $query->is_paged $query->is_posts_page $query->is_post_type_archive $query->is_preview $query->is_robots $query->is_search $query->is_single $query->is_singular $query->is_tag $query->is_tax $query->is_time $query->is_trackback $query->is_year // функции $query->is_front_page() // это главная страница? $query->is_main_query() // проверяет в главном ли цикле WordPress выполняется действие. is_post_type_archive( 'kino' ) // это post_type == kino?
Так же не забываем что pre_get_posts может намного больше:
Как добавить свои параметры в запрос не используя WP_Query?
http://onwp.ru/question/kak-dobavit-v-svoi-parametry-v-zapros-ne-ispolzuyu-wp_query