Intereting Posts
Как изменить цвет ссылок в соответствии со страницей при использовании PHP Многократные разделители Php в разрыве PHP – неожиданный конец файла Многоязычная проблема Woocommerce, Как добавить и отредактировать строку. Как установить значение POST для PHP на одной странице с помощью jQuery Как открыть календарь Outlook с помощью электронной почты или веб-страницы? Ключ разработчика, необходимый для этой операции Отчет в формате PDF Поколение в Zabbix не работает Есть ли ярлык для привязки названных параметров PDO для вставок MySQL? пустая страница с большими циклами Чтобы передать значение переменной в одной функции другой функции в том же классе Как указать SMTP-сервер для электронной почты в PHP? Сборник PHP – Копирование дубликатов при обновлении или изменении страницы Apache: встроенный PHP не работает на Linux Структурная структура ООП по иерархии PHP

WordPress объединяет запросы

У меня есть два запроса, которые мне нужно попытаться объединить, чтобы моя разбивка на страницы работала правильно, а сообщения отображаются в правильном порядке.

У меня есть один запрос:

$today = date('m/d/Y', strtotime('today')); $args = array( 'post_type' => 'workshops', "posts_per_page" => 5, "paged" => $paged, 'meta_key' => 'select_dates_0_workshop_date', 'orderby' => 'meta_value', 'order' => 'ASC', 'meta_query' => array( array( 'key' => 'select_dates_0_workshop_date', 'meta-value' => "meta_value", 'value' => $today, 'compare' => '>=', 'type' => 'CHAR' ) ) ); 

Результаты этого запроса должны появиться после запроса выше:

 $args = array( 'post_type' => 'workshops', "posts_per_page" => 5, "paged" => $paged, 'meta_key' => 'select_dates_0_workshop_date', 'orderby' => 'meta_value', 'order' => 'DESC', 'meta_query' => array( array( 'key' => 'select_dates_0_workshop_date', 'meta-value' => "meta_value", 'value' => $today, 'compare' => '<', 'type' => 'CHAR' ) ) ); 

Разница между двумя запросами заключается в следующем: 'order' и 'compare' .

Я сделал это в чистых запросах MYSQL, но я не уверен, как это сделать на WordPress

    Это обновленная версия ответа, более гибкая, чем предыдущая.

    Вот одна идея с использованием SQL UNION :

    • Мы можем использовать данные из фильтра posts_clauses для перезаписи SQL-запроса из фильтра posts_request .

    • Мы расширяем класс WP_Query для достижения нашей цели. Мы на самом деле делаем это дважды:

      • WP_Query_Empty : получить сгенерированный SQL-запрос для каждого подзапроса, но без запроса базы данных.
      • WP_Query_Combine : для получения сообщений.
    • Следующая реализация поддерживает объединение N подзапросов.

    Вот две демонстрации:

    Демонстрация № 1:

    Предположим, у вас есть шесть должностей, упорядоченных по дате (DESC):

     CCC AAA BBB CCC YYY ZZZ XXX 

    где XXX , YYY и ZZZ старше DT=2013-12-14 13:03:40 .

    Давайте закажем наши сообщения, чтобы сообщения, опубликованные после DT , упорядочивались по заголовку (ASC) и сообщения publisehd перед тем, как DT упорядочены по названию (DESC):

     AAA BBB CCC ZZZ YYY XXX 

    Затем мы можем использовать следующее:

     /** * Demo #1 - Combine two sub queries: */ $args1 = array( 'post_type' => 'post', 'orderby' => 'title', 'order' => 'ASC', 'date_query' => array( array( 'after' => '2013-12-14 13:03:40' ), ), ); $args2 = array( 'post_type' => 'post', 'orderby' => 'title', 'order' => 'DESC', 'date_query' => array( array( 'before' => '2013-12-14 13:03:40', 'inclusive' => TRUE ), ), ); $args = array( 'posts_per_page' => 1, 'paged' => 1, 'sublimit' => 1000, 'args' => array( $args1, $args2 ), ); $results = new WP_Combine_Queries( $args ); 

    Это генерирует следующий SQL-запрос:

     SELECT SQL_CALC_FOUND_ROWS * FROM ( ( SELECT wp_posts.* FROM wp_posts WHERE 1=1 AND ( ( post_date > '2013-12-14 13:03:40' ) ) AND wp_posts.post_type = 'post' AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'private') ORDER BY wp_posts.post_title ASC LIMIT 1000 ) UNION ( SELECT wp_posts.* FROM wp_posts WHERE 1=1 AND ( ( post_date <= '2013-12-14 13:03:40' ) ) AND wp_posts.post_type = 'post' AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'private') ORDER BY wp_posts.post_title DESC LIMIT 1000 ) ) as combined LIMIT 0, 10 

    Демонстрация № 2:

    Вот ваш пример:

     /** * Demo #2 - Combine two sub queries: */ $today = date( 'm/d/Y', strtotime( 'today' ) ); $args1 = array( 'post_type' => 'workshops', 'meta_key' => 'select_dates_0_workshop_date', 'orderby' => 'meta_value', 'order' => 'ASC', 'meta_query' => array( array( 'key' => 'select_dates_0_workshop_date', 'value' => $today, 'compare' => '>=', 'type' => 'CHAR', ), ) ); $args2 = array( 'post_type' => 'workshops', 'meta_key' => 'select_dates_0_workshop_date', 'orderby' => 'meta_value', 'order' => 'DESC', 'meta_query' => array( array( 'key' => 'select_dates_0_workshop_date', 'value' => $today, 'compare' => '<', 'type' => 'CHAR', ), ) ); $args = array( 'posts_per_page' => 5, 'paged' => 4, 'sublimit' => 1000, 'args' => array( $args1, $args2 ), ); $results = new WP_Combine_Queries( $args ); 

    Это должно дать вам запрос, подобный этому:

     SELECT SQL_CALC_FOUND_ROWS * FROM ( ( SELECT wp_posts.* FROM wp_posts 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) WHERE 1=1 AND wp_posts.post_type = 'workshops' AND (wp_posts.post_status = 'publish' OR wp_posts.post_author = 1 AND wp_posts.post_status = 'private') AND (wp_postmeta.meta_key = 'select_dates_0_workshop_date' AND (mt1.meta_key = 'select_dates_0_workshop_date' AND CAST(mt1.meta_value AS CHAR) >= '05/16/2014') ) GROUP BY wp_posts.ID ORDER BY wp_postmeta.meta_value ASC LIMIT 1000 ) UNION ( SELECT wp_posts.* FROM wp_posts 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) WHERE 1=1 AND wp_posts.post_type = 'workshops' AND (wp_posts.post_status = 'publish' OR wp_posts.post_author = 1 AND wp_posts.post_status = 'private') AND (wp_postmeta.meta_key = 'select_dates_0_workshop_date' AND (mt1.meta_key = 'select_dates_0_workshop_date' AND CAST(mt1.meta_value AS CHAR) < '05/16/2014') ) GROUP BY wp_posts.ID ORDER BY wp_postmeta.meta_value DESC LIMIT 1000 ) ) as combined LIMIT 15, 5 

    Демо № 3:

    Мы могли бы также объединить более двух подзапросов:

     /** * Demo #3 - Combine four sub queries: */ $args = array( 'posts_per_page' => 10, 'paged' => 1, 'sublimit' => 1000, 'args' => array( $args1, $args2, $args3, $args4 ), ); $results = new WP_Combine_Queries( $args ); 

    Классы:

    Вот демонстрационные классы:

     /** * Class WP_Combine_Queries * * @uses WP_Query_Empty * @link https://stackoverflow.com/a/23704088/2078474 * */ class WP_Combine_Queries extends WP_Query { protected $args = array(); protected $sub_sql = array(); protected $sql = ''; public function __construct( $args = array() ) { $defaults = array( 'sublimit' => 1000, 'posts_per_page' => 10, 'paged' => 1, 'args' => array(), ); $this->args = wp_parse_args( $args, $defaults ); add_filter( 'posts_request', array( $this, 'posts_request' ), PHP_INT_MAX ); parent::__construct( array( 'post_type' => 'post' ) ); } public function posts_request( $request ) { remove_filter( current_filter(), array( $this, __FUNCTION__ ), PHP_INT_MAX ); // Collect the generated SQL for each sub-query: foreach( (array) $this->args['args'] as $a ) { $q = new WP_Query_Empty( $a, $this->args['sublimit'] ); $this->sub_sql[] = $q->get_sql(); unset( $q ); } // Combine all the sub-queries into a single SQL query. // We must have at least two subqueries: if ( count( $this->sub_sql ) > 1 ) { $s = '(' . join( ') UNION (', $this->sub_sql ) . ' ) '; $request = sprintf( "SELECT SQL_CALC_FOUND_ROWS * FROM ( $s ) as combined LIMIT %s,%s", $this->args['posts_per_page'] * ( $this->args['paged']-1 ), $this->args['posts_per_page'] ); } return $request; } } // end class /** * Class WP_Query_Empty * * @link https://stackoverflow.com/a/23704088/2078474 */ class WP_Query_Empty extends WP_Query { protected $args = array(); protected $sql = ''; protected $limits = ''; protected $sublimit = 0; public function __construct( $args = array(), $sublimit = 1000 ) { $this->args = $args; $this->sublimit = $sublimit; add_filter( 'posts_clauses', array( $this, 'posts_clauses' ), PHP_INT_MAX ); add_filter( 'posts_request', array( $this, 'posts_request' ), PHP_INT_MAX ); parent::__construct( $args ); } public function posts_request( $request ) { remove_filter( current_filter(), array( $this, __FUNCTION__ ), PHP_INT_MAX ); $this->sql = $this->modify( $request ); return ''; } public function posts_clauses( $clauses ) { remove_filter( current_filter(), array( $this, __FUNCTION__ ), PHP_INT_MAX ); $this->limits = $clauses['limits']; return $clauses; } protected function modify( $request ) { $request = str_ireplace( 'SQL_CALC_FOUND_ROWS', '', $request ); if( $this->sublimit > 0 ) return str_ireplace( $this->limits, sprintf( 'LIMIT %d', $this->sublimit ), $request ); else return $request; } public function get_sql( ) { return $this->sql; } } // end class 

    Затем вы можете настроить классы для своих нужд.

    Я использую трюк, упомянутый здесь, чтобы сохранить порядок UNION . Вы можете изменить его соответствующим нашим параметром sublimit .

    Это также должно работать для основных запросов, например , с помощью фильтра posts_request .

    Надеюсь, это поможет.

    Проблема заключается в аргументе «порядок»: аргумент «meta_query» принимает массив мета-запросов, а также аргумент «отношение» (в основном, «AND» или «OR»). Это можно использовать для выбора сообщений как меньше, так и большего, чем-или-равно- $today (хотя в этот момент мета-запрос бесполезен, поскольку он выбирает все семинары («ИЛИ») или «нет» («И») К сожалению, WP_Query не позволяет произвольно сортировать результаты (переход от ближайшего ближайшего к последнему мастерству).

    Если вы знаете, как это сделать непосредственно в MySQL, вы можете рассмотреть возможность просмотра фильтров WP_Query , в posts_orderby фильтра posts_orderby . Эти фильтры позволяют начать воспроизведение с фактического SQL, сгенерированного классом WP_Query, без необходимости переключения на полностью настраиваемые запросы. Однако следует предупредить, что важно ограничить объем этих фильтров или подвергнуть их риску их применение к каждому запросу вашего сайта (в документации по фильтрам posts_where есть несколько хороших примеров того, как это сделать).