it-swarm.com.ru

Дата архивов для пользовательского типа сообщения

Я видел много вопросов/сообщений по этому поводу, но пока не нашел достойного решения. В основном я пытаюсь сделать то, что делает wp_get_archives, но для пользовательского типа записи (лично я не уверен, почему wp_get_archives не поддерживает пользовательские типы записей!).

Код, который я сейчас использую, выглядит следующим образом:

functions.php

function Cpt_getarchives_where_filter( $where , $r ) {
  $post_type = 'events';
  return str_replace( "post_type = 'post'" , "post_type = '$post_type'" , $where );
}

sidebar-events.php

add_filter( 'getarchives_where' , 'Cpt_getarchives_where_filter' , 10 , 2 );
wp_get_archives();
remove_filter('getarchives_where' , 'Cpt_getarchives_where_filter' , 10 );

Этот код отображает даты (например, апрель 2014 г., март 2014 г.) и т.д., Что замечательно, но при переходе по ссылкам просто отображается 404. URL, созданный для каждой ссылки на дату, -/2014/04 /, однако это должно быть что-то лайк/события/2014/04 /.

Есть ли способ включить "события" в URL, чтобы можно было использовать шаблон archive-events.php, и есть ли причина, по которой ссылки в настоящее время генерируют 404?

Большое спасибо за любую помощь

2
wickywills

Вы также можете выполнить фильтрацию 'month_link' для ежемесячных архивов, 'year_link' для годовых архивов и 'day_link' для ежедневных архивов.

Вы также можете написать функцию, которая расширяет wp_get_archives для работы с CPT, добавляя фильтры к 'getarchives_where' и к ссылке на архив.

function wp_get_cpt_archives( $cpt = 'post', $args = array() ) {
  // if cpt is post run the core get archives
  if ( $cpt === 'post' ) return wp_get_archives($args); 
  // if cpt doesn't exists return error
  if ( ! post_type_exists($cpt) ) return new WP_Error('invalid-post-type');
  $pto = get_post_type_object($cpt);
  // if cpt doesn't have archive return error
  if ( ! $pto = get_post_type_object( $cpt ) ) return false;
  $types = array('monthly' => 'month', 'daily' => 'day', 'yearly' => 'year');
  $type = isset( $args['type'] ) ?  $args['type'] : 'monthly';
  if ( ! array_key_exists($type, $types) ) {
    // supporting only 'monthly', 'daily' and 'yearly' archives
     return FALSE;
  }
  $done_where = $done_link = FALSE;
  // filter where
  add_filter( 'getarchives_where' , function( $where ) use (&$done_where, $cpt) {
    if ( $done_where ) return $where;
    return str_replace( "post_type = 'post'" , "post_type = '{$cpt}'" , $where );
  });
  // filter link
  add_filter( "{$types[$type]}_link", function( $url ) use (&$done_link, $pto, $cpt) {
    if ( $done_link ) return $url;
     // if no pretty permalink add post_type url var
     // if ( get_option( 'permalink_structure' ) || ! $pto->rewrite ) {
     if ( ! get_option( 'permalink_structure' ) || ! $pto->rewrite ) {
       return add_query_arg( array( 'post_type' => $cpt ), $url );
     } else { // pretty permalink
       global $wp_rewrite;
       $slug = is_array( $pto->rewrite ) ? $pto->rewrite['slug'] : $cpt;
       $base = $pto->rewrite['with_front'] ? $wp_rewrite->front : $wp_rewrite->root;
       $home = untrailingslashit( home_url( $base ) );
       return str_replace( $home,  home_url( $base . $slug ), $url );
     }
  });
  // get original echo arg and then set echo to false  
  $notecho = isset($args['echo']) && empty($args['echo']);
  $args['echo'] = FALSE; 
  // get archives
  $archives = wp_get_archives($args);
  // prevent filter running again
  $done_where = $done_link = TRUE;
  // echo or return archives
  if ( $notecho ) {
    return $archives;
  } else {
    echo $archives;
  }
}

Пожалуйста, прочитайте встроенные комментарии для получения дополнительной информации о том, как работает функция.

Теперь есть проблема. URL, такие как /events/2014/04/, не распознаются WordPress, поэтому вам нужно добавить правила reqrite, которые обрабатывают URL-адреса такого рода.

Опять же, вы можете написать функцию, которая добавляет эти правила для вас:

function generate_cpt_archive_rules( $cpt ) {
  if ( empty($cpt) || ! post_type_exists($cpt) ) return;
  global $wp_rewrite;
  $pto = get_post_type_object($cpt);
  if ( ! $pto->has_archive ) return;
  $base = $pto->rewrite['with_front'] ? $wp_rewrite->front : $wp_rewrite->root;
  $base = trailingslashit( $base );
  $slug = is_array( $pto->rewrite ) ? $pto->rewrite['slug'] : $cpt;
  $year = ltrim( $base . $slug . '/([0-9]{4})/?$', '/' );
  $month = ltrim( $base . $slug . '/([0-9]{4})/([0-9]{2})/?$', '/' );
  $day = ltrim( $base . $slug . '/([0-9]{4})/([0-9]{2})/([0-9]{2})/?$', '/' );
  $index = 'index.php?post_type=' . $cpt;
  $rules[$year] =  $index . '&m=$matches[1]';
  $rules[$month] = $index . '&m=$matches[1]$matches[2]';
  $rules[$day] = $index . '&m=$matches[1]$matches[2]$matches[3]';
  $page = 2;
  foreach ( array( $year, $month, $day ) as $rule ) {
    $paged = str_replace( '/?$', '/page/([0-9]{1,})/?$', $rule);
    $rules[$paged] = $rules[$rule] . '&paged=$matches[' . $page . ']';
    $page++;
  }
  return $rules;
}

Эта функция генерирует правила, однако вам также необходимо добавить и очистить их.

Теперь рекомендуется сбросить правила активации темы (или плагина) и зарегистрировать их в init, поэтому вы должны сделать что-то вроде:

function register_cpt_dates_rules() {
  $cpts = array( 'events' );
  foreach ( $cpts as $cpt ) {
    foreach ( generate_cpt_archive_rules( $cpt ) as $rule => $rewrite ) {
      add_rewrite_rule( $rule, $rewrite, 'top' );
    }
  }
}
// flushing on theme switch
add_action('after_switch_theme', function() {
  register_cpt_dates_rules();
  $GLOBALS['wp_rewrite']->flush_rules();
});
// registering on init
add_action( 'init', 'register_cpt_dates_rules' );

После того, как вы добавили эти функции в свой functions.php (и снова деактивировали и активировали свою тему для запуска 'after_switch_theme'), вы можете отобразить архивы, используя

wp_get_cpt_archives( 'events' );

И он будет отображать архивы для события CPT, и ссылка будет что-то /events/2014/04/.

Работает также для годовых или ежедневных архивов:

wp_get_cpt_archives( 'events', array( 'type'=>'yearly' ) );
wp_get_cpt_archives( 'events', array( 'type'=>'daily' ) );

Используя мои две функции, у вас есть супер-простой способ заставить wp_get_archives работать с CPT.

Обратите внимание, что все код здесь требует PHP 5.3+.

4
gmazzap

Я думаю, что G.M дал все необходимое. Я написал сообщение в блоге о создании постоянной ссылки для архивов дат CPT, но у меня еще не было времени получить другую часть pre_get_posts в форме блога.

Есть в основном 3 части головоломки:

  1. Генерация правил перезаписи для чтения строк даты /2014/04/30, /2014/ и т.д.
  2. Получение вашего WP_Query для распознавания запросов.
  3. и создание ссылок на страницы/архивы для виджетов боковой панели (о которых рассказывается в моем сообщении).
0
Eric Holmes