Как оформить запрос для получения статей из нескольких категорий однов

Как правильно оформить запрос в WP 2.7 Ru для получения статей из нескольких категорий одновременно?
Другими словами, выводить статью, когда она находится, к примеру, и в категории с ID=1 и категории с ID=2 одновременно?

С помощью плагина WordPress Subdomains, сделал для разных рубрик поддомены.
Тема используется WP Max.

В теме используются блоки для отображения из выбранных категорий (настраивается в теме) по несколько постов. Другими словами можно отображать несколько рубрик, на которые есть необходимость обратить внимание в первую очередь посетителя.
Не буду распыляться больше про WP Max, кто не знает, советую.

имя сайта test.info

Итак есть рубрики Россия и Украина с метками "ru" и "ua" соответственно и ID у них 1 и 2 соответственно.
С помощью плагина теперь можно заходить в рубрики по адресам ru.test.info и ua.test.info .
Теперь заходя по адресу ru.test.info или ua.test.info я вижу то же самое, если бы я заходил на test.info.

привожу пример того, как это работает сейчас:

<?php 
$featured = new WP_query(); 
//здесь  $mytheme['featured'] - это ID избранной мною темы, предположим переменная равна 3.
$featured->query('showposts=10&cat='.$mytheme['featured']); //оформляю запрос
?>

//вывожу
<?php while ($featured->have_posts()) : $featured->the_post(); ?> 
<?php endwhile; ?>

Необходимо когда попадаешь в одну из этих рубрик ( "ru" или "ua") отображать статьи которые относятся одновременно и к избранной рубрике и рубрике ru или ua, другими словами исспользовать в запросе логическое И.

Всё казалось бы хорошо и просто, если написать функцию которая могла бы проверить нахожусь ли я сейчас в рубрике RU или UA и если да, то добавить ID этой рубрики в запрос…
Это теоретически, а как сделать это практически, думал что понимал, но по-факту ошибаюсь…

вот как я это сделал:

<?php 
function sort_by_category_fun ( $ch = '', $ch2 = '', $ch3 = '' )
{//не буду вдаваться в подробности этой функции, чтобы не загромождать заголовок темы, будет надо, напишу.
//проверяю это RU или UA, если да возвращаю $ch . "ID этой рубрики" . $ch2, если нет возвращаю 
// переменную $ch3
} 
?>

<?php 
$featured = new WP_query(); 
$featured->query('showposts=10&cat='.sort_by_category_fun('',',','') .$mytheme['featured']); //оформляю запрос

//содержимое $featured->query сейчас будет следующим, если это UA: 'showposts=10&cat=2,3'
//если же это не RU или не UA то запрос будет таким: 'showposts=10&cat=3'

//казалось бы всё в порядке, перечисляем в запросе через запятую рубрики в формате: cat=1,2,итд...
//но этот запрос работает как ИЛИ, когда нужно И.
?>

//вывожу
<?php while ($featured->have_posts()) : $featured->the_post(); ?> 
<?php endwhile; ?>

Нашёл в кодексе Вордпреса описание оформления запроса
тэг category__and
и я попробовал сделать так:

<?php
$featured = new WP_query(); 
if ( is_category(1) or is_category(2) ) //если это категория RU или UA
$featured->query(  array( 'showposts' =>10, 'category__and' => array( $mytheme['featured'],sort_by_category_fun() ))  ); //оформляю запрос если это RU или UA
else $featured->query('showposts=10&cat='.$mytheme['featured']); //оформляю запрос если это не RU или UA
?>

//вывожу
<?php while ($featured->have_posts()) : $featured->the_post(); ?> 
<?php endwhile; ?>

Казалось бы вот оно, счастья, да не тут-то было…
Всё-равно это работает как ИЛИ…. 🙁

Как лучше это сделать? В чём загвоздка?

Парадоксально что запрос вида:
cat=-3,-4
работает как И не, И не

cat=1,-3,-4
работает как И, И не, И не

cat=1,2
работает как ИЛИ

Извиняюсь за флуд, тема уже была написана с менее удачным названием
Поддомены(субдомены, Subdomian) Для категорий, Miltiple Category Query

У меня похожий вопрос как здесь (выводилось последние посты не всех рубрик, а строго определённой) только со сложным запросом и не на прямую обращаясь к БД а через функцию ВордПресcа в WP Query.

У меня похожий вопрос как здесь (выводилось последние посты не всех рубрик, а строго определённой)  только со сложным запросом и не на прямую обращаясь к БД а через функцию ВордПресcа в WP Query.

Хотя, это не принципиально. главное, чтобы был результат…

Damien, Вы действительно думаете, что кто-то будет разбираться, что такое $mytheme[‘featured’] и sort_by_category_fun() , которые Вы скармливаете инициализатору массива как начальные значения?

Damien, Вы действительно думаете, что кто-то будет разбираться, что такое $mytheme['featured'] и sort_by_category_fun() , которые Вы скармливаете инициализатору массива как начальные значения?

Может странно, но я думал этим здесь и занимаются.

Суть даже не в том.
а в том, что запросы

query('cat=1,2')

работают как ИЛИ категория1 ИЛИ категория2.
при этом

query('cat=1,-2')

работают как категория1 без категории2 другими словами здесь это работает как И

И как тогда добиться чтобы получать статьи которые одновременно относятся И к категории1 И к категории2, как правильно построить запрос?

Вы же сами давали ссылку на Кодекс, где английским по белому написано
This shows posts that are in both categories 2 and 6:
query_posts(array(‘category__and’ => array(2,6)));

Вы же сами давали ссылку на Кодекс, где английским по белому написано
This shows posts that are in both categories 2 and 6: 
query_posts(array('category__and' => array(2,6)));

На стене тодже написано, а под ним …
Там же я говорю,что почему-то это не работает.

Разве? Кажется, Вы написали, что не работает вот это:
‘category__and’ => array( $mytheme[‘featured’],sort_by_category_fun() )
На что я и написал, что никто не будет разбираться с тем, что такое $mytheme[‘featured’],sort_by_category_fun().

Разве? Кажется, Вы написали, что не работает вот это:
'category__and' => array( $mytheme['featured'],sort_by_category_fun() )
На что я и написал, что никто не будет разбираться с тем, что такое $mytheme['featured'],sort_by_category_fun().

я написал так:
$featured->query( array( ‘showposts’ =>10, ‘category__and’ => array( $mytheme[‘featured’],sort_by_category_fun() )) );

я, конечно не ас но и не идиот, думаю каждый может понять, что $mytheme[‘featured’] это просто переменная.
точно так же как и что функция возвращает что-то и ничего страшного там нету….

конечно, могу упростить, собственно я так и сделал:

Как лучше это сделать? В чём загвоздка?

Парадоксально что запрос вида:
cat=-3,-4
работает как И не, И не

cat=1,-3,-4
работает как И, И не, И не

cat=1,2
работает как ИЛИ

и здесь:

Суть даже не в том.
а в том, что запросы 
query('cat=1,2')

работают как ИЛИ категория1 ИЛИ категория2.
при этом

query('cat=1,-2')

работают как категория1 без категории2 другими словами здесь это работает как И

И как тогда добиться чтобы получать статьи которые одновременно относятся И к категории1 И к категории2, как правильно построить запрос?

я, конечно не ас но и не идиот, думаю каждый может понять, что $mytheme['featured'] это просто переменная.

Значит, по-вашему я идиот? Ну спасибо. Счастливо задолбаться!

[quote=Damien]я, конечно не ас но и не идиот, думаю каждый может понять, что $mytheme['featured'] это просто переменная.

Значит, по-вашему я идиот? Ну спасибо. Счастливо задолбаться![/quote]
Спасибо за помощь и придирчивость на ровном месте.

итак, как я это сделал:
сначала теория

есть три таблицы
posts
term_relationships
term_taxonomy

Нужно получить ID только тех постов, которые удовлетворяют условие и относятся к нескольким категориям (multi category) также они опубликованы и относятся к категории.

Для этого сначала нужно склеить эти три таблицы влево в следующем порядке term_relationships, posts, term_taxonomy.
Потом нужно создать так называемую кросс-таблицу (MySQL Crosstabs) из обычной "плоской" для того, чтобы потом можно было производить выборку в ней по сложным условиям.

Вот и всё.

[code- <?php
$featured = new WP_query();
global $cat;

if (is_category())
{
//если это категория исспользуем сложный запрос
$condition = ‘cat’ . $cat . ‘=1 AND cat’ . $mytheme[‘featured’] . ‘=1’;
//для недогадливых $mytheme[‘featured’] – это просто переменная содержащая ID какой-то категории.
//здесь cat1=0 означает ИСКЛЮЧЕНИЕ.
//тоесть найти все статьи которые относяться одновременно к категории 2 или к категории 3, но ни одна из статей не пренадлежат категории 1.
//такой способ записи связан с тем, что его легче преобразовать в SQL запрос в последующем. Описание функции ниже.

$args=array(
‘showposts’ => 1,
‘post__in’ => get_posts_id_( $condition , 1)
);
}
else
{
$args=array(
‘showposts’ => 1,
‘cat’ => $mytheme[‘featured’]
);
}
$featured->query($args);
// дальше обрабатываем как обычно:
<?php while ($featured->have_posts()) : $featured->the_post(); ?>
//обработка постов….
<?php endwhile; ?>
?>[/code]
а вот функция, которая здесь используется:

<?php
//функция может выполнять более сложные запросы по поиску ID постов исходя из принадлежности последних к указанным категориям, используя в условиях логические И ИЛИ НЕ и вложенность этих условий, ограниченную только возможностями языка SQL. 
function get_posts_id_($condition, $post_limit=5, $offset=0)
{
$tok = strtok($condition,"cat");
while($tok)
{
  $categories_array 
= substr($tok, 0, stripos($tok, '=')); $tok = strtok("cat"); } $categories = implode(',',$categories_array ); //здесь мне нужно получить номера категорий, которые используются в переменной $condition //получаю их и записываю в строку через запятаю global $wpdb; $sql_condition = str_ireplace("cat", "result_table.cat", $condition); //преобразуем к обычному SQL запросу, условие заданное в $condition $sql = "SELECT result_table.ID FROM(SELECT term_relationships_new.ID "; foreach ( $categories_array as $cat_num ) { //здесь создаётся кросс-таблица $sql .= ", SUM( IF( term_relationships_new.term_id = '" . $cat_num . "', 1, 0) ) as cat" . $cat_num . " "; } $sql .= " FROM (SELECT $wpdb->posts.ID, $wpdb->term_taxonomy.term_id FROM $wpdb->term_relationships LEFT JOIN $wpdb->posts ON ($wpdb->term_relationships.object_id = $wpdb->posts.ID) LEFT JOIN $wpdb->term_taxonomy ON ($wpdb->term_relationships.term_taxonomy_id = $wpdb->term_taxonomy.term_taxonomy_id) WHERE $wpdb->term_taxonomy.term_id IN ($categories) AND $wpdb->posts.post_status = 'publish' AND $wpdb->term_taxonomy.taxonomy = 'category' ORDER BY $wpdb->posts.post_date DESC //здесь склеили таблицы и получили таблицу только с posts.ID и term_id и только те, которые относятся хотя бы к одной из категорий //и они опубликованы ) AS term_relationships_new GROUP BY term_relationships_new.ID //а теперь групируем и завершаем создание кросс-таблицы ) AS result_table WHERE $sql_condition LIMIT $post_limit OFFSET $offset //этим простым выражением мы формируем окончательный вариант того, что нужно. //как Вы помните, $sql_condition содержит условие формирования запроса //и ограничиваем количество постов. "; $results = $wpdb->get_results($sql); foreach ($results as $result_post) { $result_posts_array- = $result_post->ID; } if (!$result_posts_array) //если не найдено постов, то присвоим 0, чтобы ничего не выводить. $result_posts_array
= 0; return $result_posts_array; } ?>

Недостатки такого подхода:
1. Здесь используется SQL запрос с двойной вложенностью.
Я не знаю как можно выполнить этот запрос в один "присест".
2. Здесь выполняется запрос к базе данных дважды, – первый, когда я получаю список ID постов; второй, когда я обращаюсь стандартной формой запроса для получения содержимого постов.
Сделал так, чтобы меньше редактировать уже написанный код и использовать дальше стандартные средства WordPress’a для получения содержимого постов.

Приглашаю всех к обсуждению, как лучше выполнить задачу обсуждаемую в рамках этой темы, более элегантно, правильно.
Или как усовершенствовать уже написанный код.

Очень интересная тема, но похоже оптимизаторов кода здесь нет. Очень актуально и для меня 🙁

Сохраните первый запрос как временную таблицу, а потом сделайте по ней второй.

Человеку который плохо разбирается в php и mysql сложно понять о чем вы. 🙁

Сохраните первый запрос как временную таблицу, а потом сделайте по ней второй.

По-моему там сохраняется первый запрос во временную таблицу. Или я чего-то не понял?

Anonymous
Отправить
Ответ на: