WP_Query и использование переменной для 'cat'=> в массиве аргументов = баг WordPress?

30 янв. 2013 г., 16:35:56
Просмотры: 22.1K
Голосов: 2

Для целей этого обсуждения, вот версия моего запроса в category.php:

wp_reset_query();
$category_id = get_cat_ID(single_cat_title('', false));
$my_query = new WP_Query(array(
'posts_per_page' => SOME_DEFINED_VALUE,
'cat'  => $category_id,
'paged' => ( get_query_var('paged') ? get_query_var('paged') : 1 ),
'post_type' => array('post','post_custom_1','post_custom_2','post_custom_3')
));
// print_r($my_query);

Если коротко, это не работает. Вот что я заметил.

Когда я делаю print_r($my_query), я вижу query_vars в первой строке. Они не соответствуют моим аргументам массива. Например, posts_per_page возвращается к какому-то другому значению (не к КОНСТАНТЕ), а список post_type больше не включает post (который должен быть).

Если я удаляю строку с 'cat'=> или жестко прописываю значение ('cat'=> 3), тогда всё работает как ожидается. Оставшиеся query_vars отображаются в print_r. Всё хорошо :)

Я пробовал следующее, но безуспешно:

  • Сделать переменную КОНСТАНТОЙ, как posts_per_page (которая не вызывает проблем).
  • Конкатенация кавычек вокруг числа $category_id - Результат такой же, как и без кавычек. Не работает.
  • 'cat' => array($category_id) - Появилась ошибка - Система не приняла массив.

Есть ли у кого-нибудь предложения?

Вот что "сработало" (читай: я мог использовать мой $category_id, и это не испортило остальные аргументы в массиве WP_Query()).

'cat'  => '"-'$category_id'"',

То есть, я мог использовать отрицание ID категории. Безумно, правда?

Если я не смогу решить это правильно, я собираюсь использовать строку с разделителями-запятыми всех моих отрицаемых категорий, вырезать текущую категорию и использовать эту строку для запроса. Другими словами, если мои категории были A, B и C, вместо запроса для A (как можно было бы ожидать)

'cat' => A

Я собираюсь сделать запрос для не B, не C.

'cat' => -B,-C

Надеюсь, есть менее хакерское решение. Я потратил на это слишком много часов, и я достаточно отчаялся, чтобы использовать этот хак и закончить с этим. Тем не менее, это точно похоже на баг в ядре. Да, я использую 3.5.1 (или мы уже на .2 или .3?). Суть в том, что я на последней версии (и это делало то же самое в 3.2.x).

Кстати, я видел эту проблему, описанную в других местах (например, на форумах WP). Одно решение предлагало сделать массив аргументов не массивом, а строкой. Даже если это возможно с WP_Query, как бы я сделал список/массив для post_types в виде строки? И наконец, если я делаю что-то неправильно, то страница помощи в Codex нуждается в обновлении, да?

Помогите. :)

0
Все ответы на вопрос 4
6

Где/как вы определяете $category_id?

См. документацию Codex по параметрам категорий для WP_Query(). WP_Query() ожидает, что ID категорий будут переданы как целые числа, а не как строки:

  • Если $category_id — это целое число, передайте его в параметр 'cat'.
  • Если $category_id — это массив (ID категорий, опять же как целые числа), передайте его в параметр 'category__in'
30 янв. 2013 г. 16:42:50
Комментарии

Спасибо @Chip. Вот эта строка, прямо перед запросом:

$category_id = get_cat_ID(single_cat_title('', false));

Если я выведу её на экран, она там и выглядит корректно. Фактически, query_vars действительно содержит 'cat' => но проблема в том, что per_page и post_types ведут себя странно. Я не использую необъявленную переменную или неправильный тип. Насколько я могу судить, это не проблема. Есть другие предложения? Ещё раз спасибо.

Chief Alchemist Chief Alchemist
30 янв. 2013 г. 17:34:03

И что возвращает эта строка? Попробуйте var_dump( $category_id ).

Chip Bennett Chip Bennett
30 янв. 2013 г. 17:37:04

var_dump( $category_id ) возвращает: string(1) "7". О?

Chief Alchemist Chief Alchemist
30 янв. 2013 г. 18:01:29

Я добавил/протестировал это: $category_id = (int)get_cat_ID(single_cat_title('', false)); var_dump( $category_id ); и WP_Query игнорирует мои аргументы и использует что-то по умолчанию. Хорошая попытка, но насколько я могу судить, проблема не в типе (строка или число). И если я оберну целочисленную $var в '"'.$var.'"', это НЕ работает. НО '"-'.$var.'"'; работает. НЕ = ОК, иначе мои аргументы сбрасываются и используется что-то по умолчанию (?)

Chief Alchemist Chief Alchemist
30 янв. 2013 г. 18:07:59

Так что, просто на всякий случай, попробуй привести тип $category_id к целому числу?

Chip Bennett Chip Bennett
30 янв. 2013 г. 18:25:15

Вот так: $category_id = (int)get_cat_ID(single_cat_title('', false)); :) Да, я уже пробовал это.

Chief Alchemist Chief Alchemist
30 янв. 2013 г. 22:21:28
Показать остальные 1 комментариев
13

Думаю, это связано с тем, как вы получаете категорию. Я настроил эту функцию в блоге, над которым работаю; $category_id всегда равен 0.

Чтобы проверить, я использую эту строку для $category_id:

global $post;
$category_id = get_the_category($post->ID)[0]->term_id;

Простой способ получить первую категорию, назначенную записи.

После этого запрос работает корректно, и параметр cat в запросе заполняется.

30 янв. 2013 г. 17:05:11
Комментарии

Спасибо, @Simon. Позволь мне немного уточнить. 'cat' => $var работает (вроде бы). Он появляется в query_var. Однако, когда я использую переменную $var для этого присвоения, другие вещи начинают вести себя странно (например, posts_per_page, post_type и т.д.). Ошибки нет. Проблема в том, что массив аргументов, который я использую в WP_Query(), не совпадает с тем, что я вижу в print_r() *когда пытаюсь присвоить 'cat' => через переменную $var. Да, попробуй разобраться в этом :) Также, когда я пытаюсь использовать упомянутую тобой строку кода, я получаю: Parse error: syntax error, unexpected '[' . ??

Chief Alchemist Chief Alchemist
30 янв. 2013 г. 17:44:28

Я добавил global $post, думаю, это то, что вызывает ошибку парсинга, извини.

В своих тестах я не заметил никаких проблем, кроме пустого $category_id.

Просто замечу, я не использую print_r, который сложно читать, а использую плагин console, который позволяет просматривать переменные в консоли firebug. Это очень удобно и делает чтение намного проще.

Simon Simon
30 янв. 2013 г. 18:06:35

Ну...Я сам добавил global $post; в первый раз и всё равно получил ошибку. Наверное, поэтому я и спрашивал. Странно, да?

Chief Alchemist Chief Alchemist
30 янв. 2013 г. 22:23:25

Хорошо, это должно работать только на одной странице, а не на странице категории, извините, что упустил это! Это интересно, но, вероятно, есть объяснение вашей проблеме.

Simon Simon
30 янв. 2013 г. 22:59:22

Я проверил ваш исходный код на странице category.php, и он работает правильно. Никаких проблем с post_type или post_per_page.

Simon Simon
30 янв. 2013 г. 23:11:28

Еще раз спасибо, @Simon. Я подозреваю, что есть какая-то "утечка" добавления в другой части темы. Я не занимался созданием, я только отвечаю за улучшения. Но даже так, это баг ядра WP, на мой взгляд. Я должен либо получить ошибку / запрос должен завершиться неудачей, либо получить результаты на основе аргументов запроса. В текущем состоянии я получаю случайный запрос при определенном (но законном) условии (например, 'cat' => $var). Вопрос: Вряд ли баг в WP будет исправлен в ближайшее время, так что насчет поиска обходного пути / решения? Есть мысли? Еще раз спасибо.

Chief Alchemist Chief Alchemist
30 янв. 2013 г. 23:33:28

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

Simon Simon
30 янв. 2013 г. 23:49:04

Снова спасибо, @Simon. Хотелось бы, чтобы всё было так просто, как смена темы, но здесь задействованы дополнительные пользовательские типы записей и другие элементы, встроенные в эту кастомную тему. Я задаю запрос. Делаю запрос. WP использует другой набор аргументов. Даже если это другой плагин и т.д., это всё равно баг (с моей точки зрения). Нелогично разрешать плагинам и т.д. вмешиваться, но не давать возможности понять, какой именно отвечает за "отклонение" запроса и подмену аргументов. Это не внушает доверия к WP_Query, согласны? Более того... 'cat' => -1,-3,-4 работает, а 'cat' => 2 — нет. Разве это не баг? :(

Chief Alchemist Chief Alchemist
31 янв. 2013 г. 01:53:17

Кстати, оказалось, что "отрицательный" хак тоже не совсем работает. next_posts_link() отображается на последней странице. Это наводит меня на мысль, что используется другой набор аргументов, не тот, который я передаю со своей строкой "исключающих категорий" и другими параметрами. Теперь я в тупике.

Chief Alchemist Chief Alchemist
31 янв. 2013 г. 02:01:37

Привет @Simon - Спасибо за подсказку / толчок. В конце концов я нашел add_action( 'pre_get_posts', 'function_to_modify_the_query_in_category_php'). Да, эта функция изменяла стандартные параметры запроса. Почему в category.php тоже был код - не уверен. Очевидно, я отвлекся. Тем не менее, это не объясняет, почему 'cat'=> $var вызывал странности. Жестко заданное значение работало нормально, а переменная - нет. Это все еще кажется довольно странным, как будто это баг. Но, опять же, я тут хорошо облажался, да? Еще раз спасибо за помощь.

Chief Alchemist Chief Alchemist
31 янв. 2013 г. 03:01:27

и @Andy Killen. Тебе тоже спасибо за помощь / подсказку.

Chief Alchemist Chief Alchemist
31 янв. 2013 г. 03:01:49

Пожалуйста, @Chief Alchemist. pre_get_posts был правильным вариантом для такого поведения.

Simon Simon
31 янв. 2013 г. 12:02:17

К слову... для всех, кто это читает... пожалуйста, комментируйте свой код. Вы никогда не знаете, кому еще придется с ним работать. Простое "аргументы этого запроса изменяются функцией: xyz() в functions.php" сэкономило бы мне кучу времени. 10 секунд могут сэкономить кому-то - включая вас самих - часы работы.

Chief Alchemist Chief Alchemist
1 февр. 2013 г. 15:20:59
Показать остальные 8 комментариев
2

Я протестировал вашу функцию, и она работает нормально, так что, вероятно, у вас ошибка в другом коде темы или конфликт с плагином. Или, возможно, ваш цикл настроен неверно.

Для справки: я тестировал следующий код в category.php в теме twentyeleven, вывод был корректным, без ошибок.

wp_reset_query();
define("SOME_DEFINED_VALUE", 5);

$category_id = get_cat_ID(single_cat_title('', false));

$my_query = new WP_Query(array(
'posts_per_page' => SOME_DEFINED_VALUE,
'cat'  => $category_id,
'paged' => ( get_query_var('paged') ? get_query_var('paged') : 1 ),
'post_type' => array('post','post_custom_1','post_custom_2','post_custom_3')
));

var_dump($my_query);
30 янв. 2013 г. 18:28:19
Комментарии

Привет @Wyck - Да, я склоняюсь к такому же мнению. То есть, проблема где-то в другом месте. Я предполагаю это потому, что значения по умолчанию (те, на которые мой массив arg заменяется каким-то другим набором значений query_arr) должны откуда-то браться, верно? Но именно для этого я и использую we_reset. Это должно оставить меня с чистого листа, так? И даже в этом случае, почему установка 'cat'=> (и насколько я могу судить, только этот параметр) с переменной $var может быть проблемой. Такой уровень странности кажется мне серьезным багом. Тебе как? Все это сказано... есть какие-то мысли по решению? Или как найти ошибку / дыру в теме?

Chief Alchemist Chief Alchemist
30 янв. 2013 г. 22:27:27

Проверь этот шаблон на наличие других циклов или подключения других частей шаблонов (include или get_template_part), отключи их и посмотри, сработает ли это, удали виджеты из загрузки, отключи плагины, проверь, не перехватывает ли кто-то запрос через pre_get_posts, проверь, не использует ли кто-то еще твой $my_query (измени имя).

Wyck Wyck
31 янв. 2013 г. 00:14:57
4

Когда я разбил ваш код на управляемые части для анализа, я обнаружил, что проблема, скорее всего, связана со строкой "paged" в массиве.

wp_reset_query();
$category_id = get_cat_ID(single_cat_title('', false));

$paged = ( get_query_var('paged') ) ? get_query_var('paged') : 1 ;

$query = array(
'posts_per_page' => 5,
'cat'  => $category_id,
'paged' => $paged ,
'post_type' => array('post','custom_1','custom_2','custom_3')
);

$loop = new WP_Query( $query);

print_r($loop);

Как видите, я добавил дополнительные скобки вокруг первого get_query_var, чтобы это стало правильным тернарным оператором. Я проверил это на своем тестовом стенде, и всё работало отлично.

С уважением, Анди

30 янв. 2013 г. 21:42:57
Комментарии

Спасибо, @Andy Killen. К сожалению, это не помогло. Похоже, проблема где-то ещё в теме. Хотя я ожидал, что wp_reset_query() даст мне чистый лист, верно? Но когда 'cat' присваивается через $val, WP начинает искать какой-то другой набор аргументов. И эти аргументы действительно похожи на те, которые сайт использует в другом месте. Что я не понимаю — почему? Почему он не использует те аргументы, которые я ему передаю? И главное — раз у меня нет реальных ошибок, как мне попытаться локализовать эту "утечку"? Любые предложения были бы очень ценны. Спасибо!

Chief Alchemist Chief Alchemist
30 янв. 2013 г. 22:42:39

Я согласен с Wyck (комментарий ниже), скорее всего, проблема в другом плагине или вашей теме. Попробуйте отключить все плагины и проверить снова. Если это не поможет, попробуйте поместить ваш categories.php в тему twentyten или подобную и проверить там.

wp_reset_query() не так критичен в этой ситуации. Можно рассматривать это как вложенный цикл внутри стандартного, если хотите — раз вы используете свою переменную для хранения цикла, это не так важно.

Andy Killen Andy Killen
30 янв. 2013 г. 22:48:48

А что, если я просто сделаю обычный SQL-запрос? Это не добавит лишней нагрузки, верно? Просто мне кажется, что к тому времени, как я найду источник "утечки" — а возможно, мне это и не удастся, ведь использование переменной для триггера "бага" само по себе странно — я мог бы просто написать SQL-запрос и не париться с WP_Query() и его проблемами.

Chief Alchemist Chief Alchemist
30 янв. 2013 г. 23:37:36

На самом деле, думаю, мой План А сейчас будет заключаться в строке со всеми категориями, исключая текущую. Ой, кажется, я уже упоминал это как решение. Сумасшедшая идея, но она сработает. И если я когда-нибудь найду дыру, то просто удалю этот "хак".

Chief Alchemist Chief Alchemist
30 янв. 2013 г. 23:59:13