2013-01-23 13 views
6

Mam niestandardowy typ wiadomości "news" w mojej witrynie Wordpress. Korzystam z wtyczki Advanced Custom Fields, aby dodawać metadane do każdego postu.Niestandardowy typ wpisu rocznego/miesięcznego archiwum

Chcę utworzyć tablicę newsów w archiwum:

[2013] 
    [January] => 5 
[2012] 
    [January] => 20 
    [February] => 10 
[2011] 
    [April] => 30 

udało mi się uzyskać to działa na podstawie:

global $wpdb; 
    $news = $wpdb->get_results(
     "SELECT wp_posts.post_date, COUNT(wp_posts.ID) as count 
     FROM $wpdb->posts 
     WHERE 
     wp_posts.post_type = 'news' AND 
     wp_posts.post_status = 'publish' AND 
     wp_posts.post_date <= CURDATE() AND 
     wp_posts.post_date >= DATE_SUB(CURDATE(), INTERVAL 3 YEAR) 
     GROUP BY YEAR(wp_posts.post_date), MONTH(wp_posts.post_date) 
     ORDER BY wp_posts.post_date DESC", 
     ARRAY_A); 

    $archive = array(); 
    foreach ($news as $post): 
     $year = date('Y', strtotime($post['post_date']));  
     $month = date('m', strtotime($post['post_date']));  
     $month_name = date('F', strtotime($post['post_date'])); 
     $post['url'] = 'NOT SURE ABOUT URL'; 
     $archive[$year][$month_name] = $post; 
    endforeach; 

muszę mieć możliwość podłączenia się do konkretnych lat i miesięcy przy użyciu http://example.com/2012/ i http://example.com/2012/10/.

Ponieważ dotyczy to niestandardowego postu typu "news", nie jestem pewien, jak to się stało?

+0

Należy również wspomnieć, że gdy próbuję i przejdź do: 'http://example.com/index.php? post_type = news & year = 2012' Zostałem przekierowany na adres 'http: // example.com/ news' – dclawson

+1

możesz również spróbować tutaj: http://wordpress.stackexchange.com/ – tillinberlin

Odpowiedz

26

Aby zrobić to, czego potrzebujesz, musisz zmodyfikować przepiórki Wordpress, aby móc przechwycić dane post/year/etc post dla niestandardowego typu postu.

Można to zrobić za pomocą następującego kodu:

/** 
* Custom post type date archives 
*/ 

/** 
* Custom post type specific rewrite rules 
* @return wp_rewrite    Rewrite rules handled by Wordpress 
*/ 
function cpt_rewrite_rules($wp_rewrite) { 
    $rules = cpt_generate_date_archives('news', $wp_rewrite); 
    $wp_rewrite->rules = $rules + $wp_rewrite->rules; 
    return $wp_rewrite; 
} 
add_action('generate_rewrite_rules', 'cpt_rewrite_rules'); 

/** 
* Generate date archive rewrite rules for a given custom post type 
* @param string $cpt  slug of the custom post type 
* @return rules    returns a set of rewrite rules for Wordpress to handle 
*/ 
function cpt_generate_date_archives($cpt, $wp_rewrite) { 
    $rules = array(); 

    $post_type = get_post_type_object($cpt); 
    $slug_archive = $post_type->has_archive; 
    if ($slug_archive === false) return $rules; 
    if ($slug_archive === true) { 
     $slug_archive = $post_type->name; 
    } 

    $dates = array(
     array(
      'rule' => "([0-9]{4})/([0-9]{1,2})/([0-9]{1,2})", 
      'vars' => array('year', 'monthnum', 'day')), 
     array(
      'rule' => "([0-9]{4})/([0-9]{1,2})", 
      'vars' => array('year', 'monthnum')), 
     array(
      'rule' => "([0-9]{4})", 
      'vars' => array('year')) 
     ); 

    foreach ($dates as $data) { 
     $query = 'index.php?post_type='.$cpt; 
     $rule = $slug_archive.'/'.$data['rule']; 

     $i = 1; 
     foreach ($data['vars'] as $var) { 
      $query.= '&'.$var.'='.$wp_rewrite->preg_index($i); 
      $i++; 
     } 

     $rules[$rule."/?$"] = $query; 
     $rules[$rule."/feed/(feed|rdf|rss|rss2|atom)/?$"] = $query."&feed=".$wp_rewrite->preg_index($i); 
     $rules[$rule."/(feed|rdf|rss|rss2|atom)/?$"] = $query."&feed=".$wp_rewrite->preg_index($i); 
     $rules[$rule."/page/([0-9]{1,})/?$"] = $query."&paged=".$wp_rewrite->preg_index($i); 
    } 
    return $rules; 
} 

Można zauważyć, że mam zakodowane news do części $rules = cpt_generate_date_archives('news', $wp_rewrite); kodu. Możesz to zmienić w razie potrzeby.

Za pomocą tego kodu powinieneś być w stanie przejść do http://yoursite.com/news/2013/02/ i otrzymać listę archiwów dla tego konkretnego typu wiadomości dla tego konkretnego czasu.

W celu uzupełnienia, dołączę sposób generowania comiesięcznego widżetu archiwum w celu jego wykorzystania.

/** 
* Get a montlhy archive list for a custom post type 
* @param string $cpt Slug of the custom post type 
* @param boolean $echo Whether to echo the output 
* @return array   Return the output as an array to be parsed on the template level 
*/ 
function get_cpt_archives($cpt, $echo = false) 
{ 
    global $wpdb; 
    $sql = $wpdb->prepare("SELECT * FROM $wpdb->posts WHERE post_type = %s AND post_status = 'publish' GROUP BY YEAR($wpdb->posts.post_date), MONTH($wpdb->posts.post_date) ORDER BY $wpdb->posts.post_date DESC", $cpt); 
    $results = $wpdb->get_results($sql); 

    if ($results) 
    { 
     $archive = array(); 
     foreach ($results as $r) 
     { 
      $year = date('Y', strtotime($r->post_date)); 
      $month = date('F', strtotime($r->post_date)); 
      $month_num = date('m', strtotime($r->post_date)); 
      $link = get_bloginfo('siteurl') . '/' . $cpt . '/' . $year . '/' . $month_num; 
      $this_archive = array('month' => $month, 'year' => $year, 'link' => $link); 
      array_push($archive, $this_archive); 
     } 

     if(!$echo) 
      return $archive; 
     foreach($archive as $a) 
     { 
      echo '<li><a href="' . $a['link'] . '">' . $a['month'] . ' ' . $a['year'] . '</a></li>'; 
     } 
    } 
    return false; 
} 

Aby skorzystać z tej funkcji wystarczy dostarczyć ślimak niestandardowego typu post, tj get_cpt_archives('news'). Będzie to powrót szereg unikalnych rok/dat/links, czyli:

Array 
(
    [0] => Array 
     (
      [month] => February 
      [year] => 2013 
      [link] => http://yoursite.com/news/2013/02 
     ) 

    [1] => Array 
     (
      [month] => January 
      [year] => 2013 
      [link] => http://yoursite.com/news/2013/01 
     ) 

) 

Można pętli przez nich z foreach i wyjście je jednak chcesz.

Alternatywnie można użyć get_cpt_archives('news', true), który automatycznie wyświetli echo każdego elementu owiniętego w <li>, łączącego się z jego określonym archiwum.

Formatowanie wyjścia nie jest dokładnie to, co chcieliśmy, więc trzeba będzie dostosować go trochę, aby ją wyświetlić w formacie

Year 
    Month 
    Month 
Year 
    Month 

które wymagają.

Mam nadzieję, że to pomoże.

+0

Świetna odpowiedź, dzięki. – dclawson

+1

To nie działało za pierwszym razem. Prawdopodobnie musisz przejść do "Ustawienia-> Permalinki", wybierz niestandardowe i zapisz.Następnie ustaw go z powrotem na poprzedni i ponownie zapisz. Niektórzy ludzie mówią, że wystarczy z oszczędzaniem, ale nie dla mnie. –

+0

Dziękuję bardzo za te funkcje. Działało idealnie! Najlepsza odpowiedź na ten problem znalazłem online. –

3

Wiem, że to stary post, ale jest znacznie bardziej zwięzły sposób z tym co PO pyta:

function cpt_add_rewrite_rules() 
{ 
    $cpt = 'news'; 

    add_rewrite_rule($cpt.'/([0-9]{4})/([0-9]{1,2})/([0-9]{1,2})?$', 
     'index.php?post_type='.$cpt.'&year=$matches[1]&monthnum=$matches[2]&day=$matches[3]', 
     'top'); 

    add_rewrite_rule($cpt.'/([0-9]{4})/([0-9]{1,2})?$', 
     'index.php?post_type='.$cpt.'&year=$matches[1]&monthnum=$matches[2]', 
     'top'); 

    add_rewrite_rule($cpt.'/([0-9]{4})?$', 
     'index.php?post_type='.$cpt.'&year=$matches[1]', 
     'top'); 
} 

add_filter('init', 'cpt_add_rewrite_rules');