Архивы Произвольного Типа Записей по Годам и Месяцам
Как отобразить архивы Произвольного Типа Записей (Custom Post Type) по годам и месяцам?
Да, это возможно.
Вам нужно создать фильтр для wp_get_archives();
, чтобы он принимал параметр post_type
:
function my_custom_post_type_archive_where($where,$args){
$post_type = isset($args['post_type']) ? $args['post_type'] : 'post';
$where = "WHERE post_type = '$post_type' AND post_status = 'publish'";
return $where;
}
Затем подключите этот фильтр:
add_filter( 'getarchives_where','my_custom_post_type_archive_where',10,2);
Теперь при вызове архива для произвольного типа записей просто передайте параметр post_type:
$args = array(
'post_type' => 'your_custom_post_type',
'type' => 'monthly',
'echo' => 0
);
echo '<ul>'.wp_get_archives($args).'</ul>';

Вы пробовали это решение? Оно правильно получает список месяцев с записями из вашего CPT и количество записей, но ссылки бесполезны. При нажатии на них вы попадаете на архив месяца для всего сайта, а не для CPT.

После некоторых поисков (см. ответ Тома Новелла ниже) я отказался от месячных архивов для пользовательских типов записей. Вместо этого я использовал рубрику записей и изменил структуру постоянных ссылок на /%category%/%year%/%monthnum%/%postname%/
. Затем, возможно, используя хук, подобный приведенному выше, можно изменить ссылки, чтобы они начинались с /%category%/
вместо просто даты.

Вопрос по этому поводу. Это создает URL-адреса вида: mysite.com/2013/04
, но они ведут на 404. Пользовательский тип записей доступен по адресу: mysite.com/cats
, что наводит на мысль, что mysite.com/cats/2013/04
должен быть правильной ссылкой, но и она приводит к 404. Как заставить работать ссылки на архивы?

Еще лучше, наконец-то появился плагин, который решает эту проблему отсутствующей функциональности в WordPress. Он был создан одним из основных разработчиков ядра, пытающимся исправить эту проблему на уровне ядра. Плагин предоставлен как временное решение до тех пор, пока проблема не будет должным образом решена в ядре. https://wordpress.org/plugins/archives-for-custom-post-types/

Вы не должны так делать, официальная позиция разработчиков WordPress заключается в том, что пользовательские типы записей (custom post types) не предназначены для выполнения задач обычных записей (posts), и если вам нужны архивы по датам и т.д., значит, вы делаете что-то неправильно, и лучше использовать форматы записей (post formats) и другие средства.
Пользовательские типы записей предназначены для веб-приложений и подобных задач, тогда как создание пользовательского типа записей, который действует как вторичный или параллельный блог с другим названием, например "блог" против "новости", с теми же возможностями, не является тем, для чего предназначена эта функция, и может привести к другим техническим проблемам из-за её реализации.
Если вы всё еще настаиваете на этом, и просто использование пользовательских таксономий (custom taxonomies) и форматов записей недостаточно, вы можете добавить правила перезаписи (rewrite rules) в functions.php и перенаправлять архивы по годам/месяцам на определённых URL-адресах на страницу архива записей, а затем проверять на странице архива пользовательского типа записей, указали ли вы переменные в своих правилах перезаписи, и загружать другой шаблон, убедившись, что в правилах перезаписи установлены соответствующие значения.

Действительно странно, что они реализовали эту функциональность лишь частично. Можешь привести пример, как правильно использовать пользовательские записи?

Пользовательские записи следует использовать для всего, что не входит в сферу страниц и записей блога (или записей блога под другим названием, но работающих аналогично, например статьи/новости/дневники и т.д.)
Примеры правильного использования пользовательских записей: события, меню, локации, формы, логи и т.д.

Пользовательские записи - это по сути инструмент для создания веб-приложений, а не способ дублирования меню записей в админке для удобства редактирования (такое использование сделало бы WordPress значительно медленнее и оказалось бы более сложной задачей, чем может показаться)

Уууух. Это правильный, но печальный ответ на вопрос. Я не могу поверить, что объяснение выше основано на "нам не нужны URL с датами для CPT", скорее всего, реальная причина отказа от реализации - "URL с датами для CPT слишком сложны". ОЧЕВИДНО, что бывают случаи, когда людям нужны архивы по датам для пользовательских типов записей, и это очевидное желание нельзя просто отмахнуться, указывая на форматы записей.

Я вынужден категорически не согласиться. Пользовательские типы записей предназначены для использования в любых целях, и нигде в Codex не сказано, что они только для "веб-приложений". Кроме того, вам вполне может понадобиться раздел "новости" с собственной пользовательской таксономией и архивами для них. Или даже предложенный тип "события", который, я согласен, идеально подходит для CPT, но опять же, для них могут легко потребоваться архивы по датам.

Раздел новостей предполагает либо формат записи, либо таксономию, указывающую, что запись классифицирована как новость. Для такого не нужен пользовательский тип записи. В любом случае, чувствую, что ваше определение веб-приложения может отличаться от моего. В данном контексте я просто определю свою интерпретацию как всё, что не является статичной страницей или постом блога, требует представления контента в виде записей, и отсылаю вас к разработчику ядра WordPress, который изначально это заявил (вероятно, Otto или Nacin).

Действительно, мы определенно по-разному определяем веб-приложения. Хорошая новость в том, что Джек Ленокс из Automattic создал плагин, который теперь включает архивы для пользовательских типов записей (CPT), см. мой ответ ниже. Таким образом, мы наконец-то можем легко создавать архивы по датам для таких вещей, как "Мероприятия", которым действительно не хватало этой функциональности.

РЕДАКТИРОВАТЬ -> хотя этот ответ всё ещё работает для версий < WP4.4, начиная с версии 4.4 поддержка пользовательских типов записей теперь включена в функцию wp_get_archives()
Наконец-то появилось простое, быстрое и лёгкое решение для архивирования пользовательских типов записей по датам в WordPress! Это давняя проблема, которая задокументирована здесь в треке ядра WP.
Она ещё не решена, но один из участников трека опубликовал простой плагин на GitHub, который позволит вам создавать архивы по датам для пользовательских типов записей.
После установки этого плагина или добавления кода вручную в файл функций, вы сможете использовать архивы для пользовательских типов записей следующим образом:
<?php wp_get_archives_cpt( 'post_type=custom_post_type' ); ?>
Обратите внимание, что новая функция wp_get_archives_cpt
работает так же, как стандартная wp_get_archives
, поэтому вы можете использовать любые стандартные аргументы, которые она принимает. Однако, она просто добавляет возможность указать имя пользовательского типа записи.

Не хватает репутации, чтобы добавить это к ответу taiken, извините.
Однако хотел добавить, что его ответ сработал для меня, но ссылки были в формате 'localhost/date/2010'. В то время как мне нужен был формат 'localhost/название-записи/2010'. Я смог исправить это, используя замену строки в выводе wp_get_archives.
Таким образом, в зависимости от настроек ваших постоянных ссылок, этот код исправит проблему 404 и перенаправит ссылки на структуру постоянных ссылок пользовательского типа записи:
$yearly_archive = wp_get_archives(array( 'type' => 'yearly', 'post_type' => '<ваш тип записи>', 'echo' => '0') );
$blog_url = get_bloginfo('url');
echo str_replace(($blog_url . '/date'), ($blog_url . '<ваш слаг типа записи>'),$yearly_archive);

Не могу добавить к посту takien, поэтому вот что мне в итоге пришлось сделать:
functions.php
add_action('init', 'my_year_archive_rewrites');
function my_year_archive_rewrites() {
add_rewrite_rule('resource/news/([0-9]{4})/page/?([0-9]{1,})/?', 'index.php?post_type=news&year=$matches[1]&paged=$matches[2]', 'top');
add_rewrite_rule('resource/news/([0-9]{4})/?', 'index.php?post_type=news&year=$matches[1]', 'top');
}
add_filter('getarchives_where', 'my_custom_post_type_archive_where', 10, 2);
function my_custom_post_type_archive_where($where,$args){
$post_type = isset($args['post_type']) ? $args['post_type'] : 'post';
return "WHERE post_type = '$post_type' AND post_status = 'publish'";
}
add_filter('year_link', 'my_year_link');
function my_year_link($link) {
global $wp_rewrite;
if(true) { // здесь вы определяете, какой архив вам нужен
$link = str_replace($wp_rewrite->front, '/resource/news/', $link);
}
return $link;
}
Вызов wp_get_archives()
wp_get_archives(array('post_type'=>'news', 'type'=>'yearly'));
