WordPress 主题开发 - (九) Index模板 审校
Index.php is the most crucial WordPress Theme Template. Not only because WordPress needs to use it if you’re missing any of its brother and sister templates (like, archive.php
or tag.php
) but because the work we do here, getting this template right, will help us breeze through the rest of our templates (with the exception of the dreaded comments template; that’s just plain difficult no matter how you look at it). Please note: This lesson assumes that you have already added the basic HTML structural elements to your index.php file, which we covered in WordPress Theme Template and Directory Structure. If yourindex.php
file is empty, please work through that lesson first, and then come right back.
Index.php是WordPress主题模板里面最关键的文件。不只是因为WordPress在缺失其它兄弟模板(如archive.php和tag.php)时使用它,还因为如果我们把这个模板写好了,整个主题模板 的其它部分也就轻而易举了。
注意:本课程假设你已经在index.php文件中加入了基本的HTML结构元素,这是在本课程的第五部分里面完成的,如果没有完成,请完成后再返回到本课题。(下面也会有这个基础的结构)
Calling in the Header
头部信息调用
Open up the index.php
. We added some basic structural HTML inWordPress Theme Template and Directory Structure. Here’s whatindex.php
looked like at the end of that lesson.
打开index.php。在上一课中我们添加了基本的HTML结构,如下代码是第五节课完成时的index.php。
<div id="primary" class="content-area"> <div id="content" class="site-content"> </div><!-- #content .site-content --> </div><!-- #primary .content-area -->
Paste the following code at the top of the file, before everything else.
将如下代码粘贴在文件的顶部,在任意代码之前。
<?php /** * The main template file. * * This is the most generic template file in a WordPress theme * and one of the two required files for a theme (the other being style.css). * It is used to display a page when nothing more specific matches a query. * E.g., it puts together the home page when no home.php file exists. * Learn more: http://codex.wordpress.org/Template_Hierarchy * * @package Shape * @since Shape 1.0 */ get_header(); ?>
It’s our usual documentation information, followed by the get_header()function call at the end. This function tells WordPress to include theheader.php file.
这段代码是index.php里面通常包含的文档信息,后面跟随的是get_header()函数,该函数告诉WordPress包含head.php文件。
The Loop
主循环
Even though it’s stuck right in the middle of your template, in a metaphorical sense, index.php
begins and ends with The Loop. Without it you don’t have anything.
Here’s what it looks like.
Index.php的主体是post循环,没有这个循环什么也输出不了。如下是循环的外层框架:
1 <?php while ( have_posts() ) : the_post() ?> 2 <?php endwhile; ?>
Simple really. And not even deceptively simple. While you’ve got posts in your database your theme will loop through them and for each one, do something. Getting the “do something” just right is the tricky part. But even that can be simple.
Try out this loop to get started and we’ll work on building it up. Put the following code inside your .site-content div in index.php
.
看上去很简单吧,甚至是难以置信的简单。当数据库中存储了文章(post)后,主题会迭代遍历文章,并针对每篇文章做相应的处理。处理的逻辑写正确是有些复杂的,但是也可以很简单。试验下这个循环,将如下代码放到index.php的.site-content div 中:
1 <?php /* Start the Loop */ ?> 2 <?php while ( have_posts() ) : the_post(); ?> 3 <?php the_content(); ?> 4 <?php endwhile; ?>
Here’s what your .site-content div should look like:
这时,.site-content div 看起来是这样的:
下面是
1 <div id="content" class="site-content" role="main"> 2 <?php /* Start the Loop */ ?> 3 <?php while ( have_posts() ) : the_post(); ?> 4 <?php the_content(); ?> 5 <?php endwhile; ?> 6 </div><!-- #content .site-content -->
What do you get if you do that? All the post content in a big smushed up pile. But it could be different.
加入这段代码以后,index.php会输出什么呢?所有的文章内容都会挤成一堆输出了,但是换成另外一种输出:
<?php while ( have_posts() ) : the_post() ?> <div class="entry-summary"> <?php the_excerpt(); ?> </div><!-- .entry-summary --> <?php endwhile; ?>
Do you see what we just did there? Now you’ve got a loop that lists post excerpts inside divs, each with a class of .entry-summary. (Plus, now you can see what the_content()
and the_excerpt()
do).
看见输出什么了?现在主循环在div内部列出了文章的摘要,每个摘要以entry-summary输出。(另外,你也了解了模板标签the_content()
和 the_excerpt()
的功能)。
Basically, you make a loop (starts with while ends with endwhile) and put some stuff in it—stuff being WordPress Template Tags that pull information out of the posts we’re looping though, just like bloginfo()
pulled information out of our WordPress settings in the last lesson.
总的来说,构建循环,并且在循环内输出一些post的信息,这些信息通过WordPress的模板标签从post里面提取并输出,就象上一课里面,bloginfo()
提取WordPress的设置一样。
Alright, let’s make a really awesome loop. Let’s start with our basic, smushed up one. But we’ll make sure it’s ready for the More Tag and the Next Page Tag. We’ll also put it in its own div and let machines know it’s the content of a blog post with the microformat class “entry-content”. Finally, we want to display excerpts on search result pages, and the full content on all other pages. Here’s what it looks like. No need to paste anything yet, just observe.
现在开始撰写一个酷比的循环吧。从最基础的那个,就从把所有信息都堆积在一起输出的那个版本开始。但是我们将让它可以输出“更多”(More Tag)标签和“下一页”(Next Page Tag),我们还将文章的信息放在它自己的div中,让机器知道这是文章的内容,使用格式类:entry-content。最后,我们将在search结果页中显示摘要(excerpts标签),而所有其它的页则输出完整的内容。下面是当前版本的代码。(只是看下,不要粘贴,下面还会继续改进)
1 <?php if ( is_search() ) : // Only display Excerpts for Search ?> 2 <div class="entry-summary"> 3 <?php the_excerpt(); ?> 4 </div> <!-- .entry-summary --> 5 <?php else : ?> 6 <div class="entry-content"> 7 <?php the_content( __( 'Continue reading <span class="meta-nav">→</span>', 'shape' ) ); ?> 8 <?php wp_link_pages( array( 'before' => '<div class="page-links">' . __( 'Pages:', 'shape' ), 'after' => '</div>' ) ); ?> 9 </div> <!-- .entry-content --> 10 <?php endif; ?>
How about the post title? That’s pretty simple too. We’ll use the Template Tag the_title()
to get the title of the post and wrap it in an <a>
tag that links to the_permalink()
(that’s the permanent link to any particular post). We’ll also add in a title attribute and another microformat (bookmark) that tells machines (like Google) that this is the permalink to a blog post. Here’s how our code looks so far, with the title added. Again, hold off on pasting anything for now.
那么文章标题在哪?也很简单。使用模板标签the_title() 获取文章的标题,使用<a>标签包围它,链接则指向
1 <header class="entry-header">the_permalink()
(这是指向post的永久链接)。我们也会添加title属性和bookmark属性,告诉机器(如谷歌)这是一个指向blog文章的永久链接。下面是代码看起来的样式,同样,暂时不要粘贴它。
2 <h1 class="entry-title">
3 <a href="<?php the_permalink(); ?>"
4 title="<?php echo esc_attr( sprintf( __( 'Permalink to %s', '_s' ), the_title_attribute( 'echo=0' ) ) ); ?>"
5 rel="bookmark"><?php the_title(); ?></a>
6 </h1>
7 </header>
8 <!-- .entry-header -->
9 <?php if ( is_search() ) : // Only display Excerpts for Search ?>
10 <div class="entry-summary">
11 <?php the_excerpt(); ?>
12 </div>
13 <!-- .entry-summary -->
14 <?php else : ?>
15 <div class="entry-content">
16 <?php the_content( __( 'Continue reading <span class="meta-nav">→</span>', 'shape' ) ); ?>
17 <?php wp_link_pages( array( 'before' => '<div class="page-links">' . __( 'Pages:', 'shape' ), 'after' => '</div>' ) ); ?>
18 </div>
19 <!-- .entry-content -->
20 <?php endif; ?>
Now for all the extra bits that attend to any blog post: who wrote it, the time it was published, categories, tags, comments links. I like to break all this up into two sections: the meta stuff (author and entry date) which I put before the post content, and the utility stuff (categories, tags and comments link) that I put after the content. We’ll also put the post in its own containing article
element with the title.
下面就是处理文章的额外信息了,作者,发布时间,类别,标签,评论链接。我将这些信息分为两部分,元数据(作者及发布时间),这在文章内容之前输出;工具部分(类别,标签及评论链接),这些在内容之后输出。同时也将文章及标题放在包围它的article元素中。
Let’s take a look at the whole loop together. I’ve inserted some PHP comments in here to help guide you along. Still no need to paste anything yet (we’ll do so very shortly, I promise). Just watch, and learn.
现在我们看下将所有的信息放在一起的主循环,代码里面会添加一些PHP注释,以帮助理解。同样,这个版本只是出于学习的目的,还不到粘贴的时候。
1 <?php /* The Loop — with comments! */ ?> 2 <?php while ( have_posts() ) : the_post() ?> 3 <?php /* Create an HTML5 article section with a unique ID thanks to the_ID() and semantic classes with post_class() */ ?> 4 <article id="post-<?php the_ID(); ?>" <?php post_class(); ?>> 5 <header class="entry-header"> 6 <h1 class="entry-title"><a href="<?php the_permalink(); ?>" title="<?php echo esc_attr( sprintf( __( 'Permalink to %s', '_s' ), the_title_attribute( 'echo=0' ) ) ); ?>" rel="bookmark"><?php the_title(); ?></a></h1> 7 <?php // if ( 'post' == get_post_type() ) : // Only display post date and author if this is a Post, not a Page. ?> 8 <div class="entry-meta"> 9 <?php shape_posted_on(); ?> 10 </div><!-- .entry-meta --> 11 <?php endif; ?> 12 </header><!-- .entry-header --> 13 <?php if ( is_search() ) : // Only display Excerpts on Search results pages ?> 14 <div class="entry-summary"> 15 <?php the_excerpt(); ?> 16 </div><!-- .entry-summary --> 17 <?php else : ?> 18 <div class="entry-content"> 19 <?php the_content( __( 'Continue reading <span class="meta-nav">→</span>', 'shape' ) ); ?> 20 <?php wp_link_pages( array( 'before' => '<div class="page-links">' . __( 'Pages:', 'shape' ), 'after' => '</div>' ) ); ?> 21 </div><!-- .entry-content --> 22 <?php endif; ?> 23 <?php /* Show the post's tags, categories, and a comment link. */ ?> 24 <footer class="entry-meta"> 25 <?php if ( 'post' == get_post_type() ) : // Hide category and tag text for Pages in Search results ?> 26 <?php 27 /* translators: used between list items, there is a space after the comma */ 28 $categories_list = get_the_category_list( __( ', ', 'shape' ) ); 29 if ( $categories_list && shape_categorized_blog() ) : 30 ?> 31 <span class="cat-links"> 32 <?php printf( __( 'Posted in %1$s', 'shape' ), $categories_list ); ?> 33 </span> 34 <?php endif; // End if categories ?> 35 <?php 36 /* translators: used between list items, there is a space after the comma */ 37 $tags_list = get_the_tag_list( '', __( ', ', 'shape' ) ); 38 if ( $tags_list ) : 39 ?> 40 <span class="sep"> | </span> 41 <span class="tag-links"> 42 <?php printf( __( 'Tagged %1$s', 'shape' ), $tags_list ); ?> 43 </span> 44 <?php endif; // End if $tags_list ?> 45 <?php endif; // End if 'post' == get_post_type() ?> 46 <?php if ( ! post_password_required() && ( comments_open() || '0' != get_comments_number() ) ) : ?> 47 <span class="sep"> | </span> 48 <span class="comments-link"><?php comments_popup_link( __( 'Leave a comment', 'shape' ), __( '1 Comment', 'shape' ), __( '% Comments', 'shape' ) ); ?></span> 49 <?php endif; ?> 50 <?php edit_post_link( __( 'Edit', 'shape' ), '<span class="sep"> | </span><span class="edit-link">', '</span>' ); ?> 51 </footer><!-- .entry-meta --> 52 <?php /* Close up the article and end the loop. */ ?> 53 </article><!-- #post-<?php the_ID(); ?> --> 54 <?php endwhile; ?>
To display the meta stuff (author and post date), we’re calling a function called shape_posted_on() (line 10 above). We’ll create that function a little bit later.
为显示元数据(作者与发布日期),需要调用 一个函数shape_posted_on() (上面的第9行),这在稍后创建。
For now, let’s talk more about the utility stuff in the code block (categories and tags), because it’s… complicated. Here I think you’ll see the benefit of getting something right once and standing on the shoulders of others. It’s complicated because we need to account for a few different scenarios: the existence of only one category and multiple tags; one category and no tags; multiple categories and multiple tags; or multiple categories and no tags. Also, we have to hide the category and tag links for Pages on Search results pages. Finally, we want to display a comments link only if comments are open or if there is at least one comment. We also want to print a link to our permalink here for bookmarking purposes and the edit post link at the end for site administrators.
现在,让我们来谈谈了解代码块中(类别和标签)的工具部分,因为它有些复杂。在这里,我想你会看到把功能写正确,然后重复使用它的好处(注:指提取函数作代码重用)。这是复杂的,因为我们需要考虑几种不同的情景:只有一个类别和多个标签的存在;只有一个类别,并没有标签;多个类别和多个标签,或者是多个类别但并没有标签。此外,需要在搜索结果页上,隐藏分类和标签页面链接。最后,我们要显示评论链接,仅当打开评论或至少有一个评论时。我们也想打印指向我们的永久链接以用作标记,最后则为管理员显示编辑链接。
And that means … what looks like a mess of IF statements, as you can see if you look back up at lines 26 through 57 in the previous code example. It can be daunting. The code is commented but remember to look for the blocks of IF and ELSEIF statements and you’ll be fine.
Adding metadata functions Now, let’s create the shape_posted_on() function. We’ll also add shape_categorized_blog() (line 32 above), a function we use to check if the blog has more than 1 category.
Since these are functions we can reuse, we’ll put them in template-tags.php
. Remember that file, from Setting Up Your Theme Functions? Open it up, and add:
这意味着......会需要一个乱七八糟的IF语句。你可以看到,如果你回头看下前面的代码示例的26行至57行。这可能有点吓人。该代码中有注释,但记得看看if和elseif语句块,感觉就不是那么复杂了。。
添加元数据函数,现在,让我们创建shape_posted_on()函数。我们还将添加shape_categorized_blog()(32行以上),我们用它来检查,文章是否拥有超过一个类别。
由于这些都是我们可以重用的功能,我们将把它们放在template-tags.php文件中
。想起这个文件没?前面的课程里面我们创建了它,打开它,并添加:
1 if ( ! function_exists( 'shape_posted_on' ) ) : 2 /** 3 * Prints HTML with meta information for the current post-date/time and author. 4 * 5 * @since Shape 1.0 6 */ 7 function shape_posted_on() { 8 printf( __( 'Posted on <a href="%1$s" title="%2$s" rel="bookmark"><time class="entry-date" datetime="%3$s" pubdate>%4$s</time></a><span class="byline"> by <span class="author vcard"><a class="url fn n" href="%5$s" title="%6$s" rel="author">%7$s</a></span></span>', 'shape' ), 9 esc_url( get_permalink() ), 10 esc_attr( get_the_time() ), 11 esc_attr( get_the_date( 'c' ) ), 12 esc_html( get_the_date() ), 13 esc_url( get_author_posts_url( get_the_author_meta( 'ID' ) ) ), 14 esc_attr( sprintf( __( 'View all posts by %s', 'shape' ), get_the_author() ) ), 15 esc_html( get_the_author() ) 16 ); 17 } 18 endif; 19 /** 20 * Returns true if a blog has more than 1 category 21 * 22 * @since Shape 1.0 23 */ 24 function shape_categorized_blog() { 25 if ( false === ( $all_the_cool_cats = get_transient( 'all_the_cool_cats' ) ) ) { 26 // Create an array of all the categories that are attached to posts 27 $all_the_cool_cats = get_categories( array( 28 'hide_empty' => 1, 29 ) ); 30 // Count the number of categories that are attached to the posts 31 $all_the_cool_cats = count( $all_the_cool_cats ); 32 set_transient( 'all_the_cool_cats', $all_the_cool_cats ); 33 } 34 if ( '1' != $all_the_cool_cats ) { 35 // This blog has more than 1 category so shape_categorized_blog should return true 36 return true; 37 } else { 38 // This blog has only 1 category so shape_categorized_blog should return false 39 return false; 40 } 41 } 42 /** 43 * Flush out the transients used in shape_categorized_blog 44 * 45 * @since Shape 1.0 46 */ 47 function shape_category_transient_flusher() { 48 // Like, beat it. Dig? 49 delete_transient( 'all_the_cool_cats' ); 50 } 51 add_action( 'edit_category', 'shape_category_transient_flusher' ); 52 add_action( 'save_post', 'shape_category_transient_flusher' );
In shape_posted_on(), we’re using a bunch of template tags to grab the post’s date, time, author, author archive URL, and permalink.
In shape_categorized_blog(), we’re retrieving all of the categories that have at least one post, and storing them into a temporary variable (known as a “transient”) — $all_the_cool_cats — in array format. If there is more than one category, categories will show up in the post utility links (e.g. “Filed under: Category Name”).
In the last function, shape_category_transient_flusher(), we delete the temporary variable, $all_the_cool_cats, whenever we 1) edit a category; or 2) save a post. Why? Because that’s when you might add new categories. By deleting $all_the_cool_cats, you force it to constantly update itself, so that it stays current with the number of categories you have on your blog.
在shape_posted_on()中,我们使用大量的模板标签,提取文章的日期,时间,作者,作者存档网址及固定链接。
在shape_categorized_blog(),我们要检索所有至少有一个文章的类别,并将其存储到一个临时变量(被称为“瞬态”transient,即易变的)$ all_the_cool_cats 中,这个变量是数组形式的 。如果有一个以上的类别,类别将显示在后面的工具链接(如“下一篇:分类名称”)。
在最后一个函数,shape_category_transient_flusher()里,我们删除临时变量,$ all_the_cool_cats,只要我们1)编辑类别,或2)保存文章。为什么呢?因为这时候你可能会添加新的类别。通过删除$ all_the_cool_cats,你强迫它不断地更新,以使其保持博客中最新的类别信息。
Simplifying Our Index Template
简化Index模板
Now we’ve got the Loop in place. It’s shaping up! Now, let’s make this even better. Since we’re going to use the code inside the Loop in multiple templates, wouldn’t it be nice if we could write this code once and call it up whenever we need it, instead of replicating it across template files?
Wouldn’t be nice, also, if we had a clean way to change the presentation of posts for each Post Format that our theme supports?
Luckily for us, there’s a nifty WordPress function, get_template_part(), that we can use to accomplish all of the above.
According to the WordPress Codex, get_template_part() lets you:
load a template part into a template (other than header, sidebar, footer). Makes it easy for a theme to reuse sections of code and an easy way for child themes to replace sections of their parent theme.
Since we’re going to reuse the code inside our Loop, let’s place this code into a “template part” that we can load into the theme via get_template_part() whenever we need it.
This is why I told you to hold off on pasting any of the Loop code into index.php
. But now it’s time to get a-pastin’. Open content.php
, and add the following code (it’s the same as the previous code example, with some documentation added at the top).
现在我们已经让主循环准备就绪了。它已经成型了,现在,让我们更进一步。既然我们要在多个模板中使用循环内代码,岂不是很好,如果我们能一次写这段代码,我们需要它时就调用它,而不是复制代码?
如果我们有一个干净的方式,支持更改每个文章的展示格式,这样岂不更好?
很幸运地,有一个漂亮的WordPress的功能, get_template_part ( ) ,我们可以用它来完成上述所有需求。
据WordPress的Codex站点,使用 get_template_part ( ) ,您可以:
加载模板部分到模板(除去头,侧边栏,页脚) 。很容易让子主题重用部分的代码并以一种简单的方式,让子主题取代部分其父主题。
既然我们要在我们的循环重用这份代码,让我们将这些代码放入“模板片”(template part),每当我们需要把这段代码时,我们可以通过get_template_part ()将模板片加载到主题中去。
这就是为什么我告诉你先不要粘贴任何循环代码到index.php上的原因。但是现在是粘贴的时候了。打开content.php ,并添加下面的代码(这与前面的代码示例一样,只是在上面添加了一些注释) 。
1 <?php 2 /** 3 * @package Shape 4 * @since Shape 1.0 5 */ 6 ?> 7 <article id="post-<?php the_ID(); ?>" <?php post_class(); ?>> 8 <header class="entry-header"> 9 <h1 class="entry-title"><a href="<?php the_permalink(); ?>" title="<?php echo esc_attr( sprintf( __( 'Permalink to %s', 'shape' ), the_title_attribute( 'echo=0' ) ) ); ?>" rel="bookmark"><?php the_title(); ?></a></h1> 10 <?php if ( 'post' == get_post_type() ) : ?> 11 <div class="entry-meta"> 12 <?php shape_posted_on(); ?> 13 </div><!-- .entry-meta --> 14 <?php endif; ?> 15 </header><!-- .entry-header --> 16 <?php if ( is_search() ) : // Only display Excerpts for Search ?> 17 <div class="entry-summary"> 18 <?php the_excerpt(); ?> 19 </div><!-- .entry-summary --> 20 <?php else : ?> 21 <div class="entry-content"> 22 <?php the_content( __( 'Continue reading <span class="meta-nav">→</span>', 'shape' ) ); ?> 23 <?php wp_link_pages( array( 'before' => '<div class="page-links">' . __( 'Pages:', 'shape' ), 'after' => '</div>' ) ); ?> 24 </div><!-- .entry-content --> 25 <?php endif; ?> 26 <footer class="entry-meta"> 27 <?php if ( 'post' == get_post_type() ) : // Hide category and tag text for pages on Search ?> 28 <?php 29 /* translators: used between list items, there is a space after the comma */ 30 $categories_list = get_the_category_list( __( ', ', 'shape' ) ); 31 if ( $categories_list && shape_categorized_blog() ) : 32 ?> 33 <span class="cat-links"> 34 <?php printf( __( 'Posted in %1$s', 'shape' ), $categories_list ); ?> 35 </span> 36 <?php endif; // End if categories ?> 37 <?php 38 /* translators: used between list items, there is a space after the comma */ 39 $tags_list = get_the_tag_list( '', __( ', ', 'shape' ) ); 40 if ( $tags_list ) : 41 ?> 42 <span class="sep"> | </span> 43 <span class="tag-links"> 44 <?php printf( __( 'Tagged %1$s', 'shape' ), $tags_list ); ?> 45 </span> 46 <?php endif; // End if $tags_list ?> 47 <?php endif; // End if 'post' == get_post_type() ?> 48 <?php if ( ! post_password_required() && ( comments_open() || '0' != get_comments_number() ) ) : ?> 49 <span class="sep"> | </span> 50 <span class="comments-link"><?php comments_popup_link( __( 'Leave a comment', 'shape' ), __( '1 Comment', 'shape' ), __( '% Comments', 'shape' ) ); ?></span> 51 <?php endif; ?> 52 <?php edit_post_link( __( 'Edit', 'shape' ), '<span class="sep"> | </span><span class="edit-link">', '</span>' ); ?> 53 </footer><!-- .entry-meta --> 54 </article><!-- #post-<?php the_ID(); ?> -->
Now, return to index.php, and remove all of the code that’s between<div id="content" class="site-content">
and </div><!-- #content .site-content -->
. Replace it with the following.
现在,回到index.php,并删除<div id="content" class="site-content">与</div><!-- #content .site-content –>间的所有内容
。用下面的代码替换之:
1 <?php if ( have_posts() ) : ?> 2 <?php /* Start the Loop */ ?> 3 <?php while ( have_posts() ) : the_post(); ?> 4 <?php 5 /* Include the Post-Format-specific template for the content. 6 * If you want to overload this in a child theme then include a file 7 * called content-___.php (where ___ is the Post Format name) and that will be used instead. 8 */ 9 get_template_part( 'content', get_post_format() ); 10 ?> 11 <?php endwhile; ?> 12 <?php endif; ?>
Do you see what we’re doing here? In plain English, this means: “Fill this Loop with the code inside content.php by default. But first, check the Post Format for this post. Search the theme files for a Post-Format-Specific template, such as content-aside.php, or content-quote.php. If you find one, load that template for this post instead. Otherwise, load content.php.”
And there we have it. A clean structure for our Loop that we can reuse multiple times. Plus, we can now create a different layout for our post formats.
The Aside Post Format
We added support for the Aside post format earlier. So let’s do something with it. How you display posts with each format is up to you, but the guidelines on the Codex are a good starting point.
According to the guidelines, Aside posts are intended to be short and sweet, and they’re typically formatted without a title. Let’s do that. Let’s also hide the author name, and categories and tags.
Back in WordPress Theme Template & Directory Structure, we createdcontent-aside.php
, a Post-Format-specific template just for Aside posts. Open it now, and paste the following.
看看我们在这里做什么?简单的说,就是: “ 默认使用content.php里面的代码填充这个循环。但首先,检查后对这篇文章的格式。在主题内搜索特定文章格式的模板,如content-aside.php的,或content-quote.php的主题文件。如果你找到了该模板,则加载该模板。否则,加载的content.php 。“
于是就有了这样的代码。一个我们可以多次重复使用的干净的循环结构。另外,我们现在可以为post格式创建不同的布局。
The Aside Post Format 除了邮政格式
前面我们添加了Aside Post Format。所以,让我们用它做点事。如何显示每种格式的文章取决于主题制作者,但Codex的指南是一个很好的起点。
根据指南,边栏文章一般较短且是些愉快的内容,他们通常的格式是没有标题。让我们做到这一点。同时也需要隐藏作者姓名,类别和标签。
早在WordPress主题模板和目录结构,我们创建了content aside.php ,一个用于边栏文章的特定Post模式模板。现在打开它,并粘贴以下代码:。
1 <?php 2 /** 3 * The template for displaying posts in the Aside post format 4 * @package Shape 5 * @since Shape 1.0 6 */ 7 ?> 8 <article id="post-<?php the_ID(); ?>" <?php post_class(); ?>> 9 <header class="entry-header"> 10 <h1 class="entry-title"><a href="<?php the_permalink(); ?>" title="<?php echo esc_attr( sprintf( __( 'Permalink to %s', 'shape' ), the_title_attribute( 'echo=0' ) ) ); ?>" rel="bookmark"><?php the_title(); ?></a></h1> 11 </header><!-- .entry-header --> 12 <?php if ( is_search() ) : // Only display Excerpts for Search ?> 13 <div class="entry-summary"> 14 <?php the_excerpt(); ?> 15 </div><!-- .entry-summary --> 16 <?php else : ?> 17 <div class="entry-content"> 18 <?php the_content( __( 'Continue reading <span class="meta-nav">→</span>', 'shape' ) ); ?> 19 <?php wp_link_pages( array( 'before' => '<div class="page-links">' . __( 'Pages:', 'shape' ), 'after' => '</div>' ) ); ?> 20 </div><!-- .entry-content --> 21 <?php endif; ?> 22 <footer class="entry-meta"> 23 <a href="<?php the_permalink(); ?>" title="<?php echo esc_attr( sprintf( __( 'Permalink to %s', 'shape' ), the_title_attribute( 'echo=0' ) ) ); ?>" rel="bookmark"><?php echo get_the_date(); ?></a> 24 <?php if ( ! post_password_required() && ( comments_open() || '0' != get_comments_number() ) ) : ?> 25 <span class="sep"> | </span> 26 <span class="comments-link"><?php comments_popup_link( __( 'Leave a comment', 'shape' ), __( '1 Comment', 'shape' ), __( '% Comments', 'shape' ) ); ?></span> 27 <?php endif; ?> 28 <?php edit_post_link( __( 'Edit', 'shape' ), '<span class="sep"> | </span><span class="edit-link">', '</span>' ); ?> 29 </footer><!-- .entry-meta --> 30 </article><!-- #post-<?php the_ID(); ?> -->
You’ll see that it’s nearly identical to content.php
, minus the title, author name, categories, and tags.
And there you have it. A Post-Format-Specific template!
Navigation
Now we need a way to navigate back through posts — both on single posts and on archive pages.
For archive pages, we’ll do this with 2 WordPress Template Tags:next_posts_link()
and previous_posts_link()
. These 2 functions … they don’t do what you think they do. I think the WordPress codex says it best.
- next posts link
- This creates a link to the previous posts. Yes, it says “next posts,” but it’s named that just to confuse you.
- previous posts link
- This creates a link to the next posts. Yes, it says “previous posts,” but it’s named that just to confuse you.
Just like everything in index.php
, post navigation needs to be given some careful thought when we’re building it for the first time because we’re going to wind up using it on almost every page in our blog.
你会发现,它是几乎与content.php相同,只是去掉了标题,作者姓名,类别和标签。
你有它。发表特定格式的模板!
导航
现在我们需要一个方法来导航来在post间跳转 - 无论是在单一post和存档页面间。
对于存档页面,我们将使用两个WordPress模板标签来实现导航:next_posts_link()和previous_posts_link()。这2个功能...他们并不是像你想的那样工作。我认为WordPress的Codex里面的描述最恰当。
下一篇链接(next posts link)
这将创建一个链接指向前一篇post。是的,它的说的是:“下一篇”但它的命名,仅仅是用来迷惑你。
以前的帖子链接(next posts link)
这将创建一个链接指向下一个篇post。是的,它说的是:“上一篇,”但它的命名,仅仅是用来迷惑你。
就在index.php中做的那样,post 导航需要仔细的考虑,当我们第一次建设,因为我们要在我们的博客上几乎每一页使用它。
I like to have post navigation above and below the content. Depending on how you use this code in any particular situation, you may not use it though. No matter, we can always hide it like so.
我倾向于在POST内容的上方和下方放置导航。在有些特定的情况下,您可能无法不会使用它。无论如何,我们总是可以像这样隐藏它。
1 .single #nav-above { 2 display:none; 3 }
That CSS will hide post navigation above the content on single posts.
Just like we did for the loop, we’re going to place the code for our navigation inside a multipurpose function that can output navigation for both single posts and archive pages. We’ll call the function in our templates wherever we want to show navigation. This way, we avoid unnecessary code repetition.
Return to inc/template-tags.php
. That’s where we’re going to place our navigation function. Add the following, at the end of the file.
这段CSS对于single post里面的内容隐藏导航。
就像对循环做的修改一样,我们要在一种多用途的函数内为我们的导航放置代码,函数可以输出单帖导航和归档页内的导航。我们会在模板内想要显示导航的地方调用该函数,这样,我们就避免了不必要的代码重复。
返回INC/template-tags.php。这就是我们要放置导航函数的地方。在该文件的末尾添加下面的内容:
1 if ( ! function_exists( 'shape_content_nav' ) ): 2 /** 3 * Display navigation to next/previous pages when applicable 4 * 5 * @since Shape 1.0 6 */ 7 function shape_content_nav( $nav_id ) { 8 global $wp_query, $post; 9 // Don't print empty markup on single pages if there's nowhere to navigate. 10 if ( is_single() ) { 11 $previous = ( is_attachment() ) ? get_post( $post->post_parent ) : get_adjacent_post( false, '', true ); 12 $next = get_adjacent_post( false, '', false ); 13 if ( ! $next && ! $previous ) 14 return; 15 } 16 // Don't print empty markup in archives if there's only one page. 17 if ( $wp_query->max_num_pages < 2 && ( is_home() || is_archive() || is_search() ) ) 18 return; 19 $nav_class = 'site-navigation paging-navigation'; 20 if ( is_single() ) 21 $nav_class = 'site-navigation post-navigation'; 22 ?> 23 <nav role="navigation" id="<?php echo $nav_id; ?>" class="<?php echo $nav_class; ?>"> 24 <h1 class="assistive-text"><?php _e( 'Post navigation', 'shape' ); ?></h1> 25 <?php if ( is_single() ) : // navigation links for single posts ?> 26 <?php previous_post_link( '<div class="nav-previous">%link</div>', '<span class="meta-nav">' . _x( '←', 'Previous post link', 'shape' ) . '</span> %title' ); ?> 27 <?php next_post_link( '<div class="nav-next">%link</div>', '%title <span class="meta-nav">' . _x( '→', 'Next post link', 'shape' ) . '</span>' ); ?> 28 <?php elseif ( $wp_query->max_num_pages > 1 && ( is_home() || is_archive() || is_search() ) ) : // navigation links for home, archive, and search pages ?> 29 <?php if ( get_next_posts_link() ) : ?> 30 <div class="nav-previous"><?php next_posts_link( __( '<span class="meta-nav">←</span> Older posts', 'shape' ) ); ?></div> 31 <?php endif; ?> 32 <?php if ( get_previous_posts_link() ) : ?> 33 <div class="nav-next"><?php previous_posts_link( __( 'Newer posts <span class="meta-nav">→</span>', 'shape' ) ); ?></div> 34 <?php endif; ?> 35 <?php endif; ?> 36 </nav><!-- #<?php echo $nav_id; ?> --> 37 <?php 38 } 39 endif; // shape_content_nav
Now we’re going to call this function in our index template. Return to index.php
and add the following just before the Loop.
现在,我们要在我们的索引模板调用此函数。返回index.php并在循环前添加以下代码。
<?php shape_content_nav( 'nav-above' ); ?>
Just after the Loop, add the following code.
在循环后面添加如下代码
1 <?php shape_content_nav( 'nav-below' ); ?>
Your index.php
file should now look like this.
下面代码就是index.php文件现在的内容:
1 <?php 2 /** 3 * The main template file. 4 * 5 * This is the most generic template file in a WordPress theme 6 * and one of the two required files for a theme (the other being style.css). 7 * It is used to display a page when nothing more specific matches a query. 8 * E.g., it puts together the home page when no home.php file exists. 9 * Learn more: http://codex.wordpress.org/Template_Hierarchy 10 * 11 * @package Shape 12 * @since Shape 1.0 13 */ 14 get_header(); ?> 15 <div id="primary" class="content-area"> 16 <div id="content" class="site-content" role="main"> 17 <?php if ( have_posts() ) : ?> 18 <?php shape_content_nav( 'nav-above' ); ?> 19 <?php /* Start the Loop */ ?> 20 <?php while ( have_posts() ) : the_post(); ?> 21 <?php 22 /* Include the Post-Format-specific template for the content. 23 * If you want to overload this in a child theme then include a file 24 * called content-___.php (where ___ is the Post Format name) and that will be used instead. 25 */ 26 get_template_part( 'content', get_post_format() ); 27 ?> 28 <?php endwhile; ?> 29 <?php shape_content_nav( 'nav-below' ); ?> 30 <?php endif; ?> 31 </div><!-- #content .site-content --> 32 </div><!-- #primary .content-area -->
Look at shape_content_nav() in template-tags.php
.
看下template-tags.php函数的内容:
1 function shape_content_nav( $nav_id ) {
You can see that $nav_id is the variable that holds the parameter we passed to the function when we called it in the index template. $nav_id is equal to ‘nav-above’ and ‘nav-below’ for the top and bottom navigation, respectively. What does the function do with $nav_id? Take a look at this line:
$ nav_id用来保存,在index.php中调用函数时传递的参数。$ nav_id等于'nav_above' 和 “nav-below”分别对应于顶部和底部的导航。函数是怎样使用$ nav_id的?看看下面这行代码:
1 <nav role="navigation" id="<?php echo $nav_id; ?>" class="<?php echo $nav_class; ?>">
$nav_id becomes the ID selector name of the nav
element. This allows you to target this particular element with CSS, such as to hide it or to give it a distinct style.
$ nav_id成为nav元素的ID选择器名。这可以让您针对这个特殊的元素设计CSS,例如是要隐藏它,或是给它一个独特的风格。
Adding the no-results.php Template Part
添加no-results.php 模板片
Looking back over at index.php
, you can see that the Loop loadscontent.php
if posts exist in the database. But what happens if noposts exist? Let’s display a message if posts can’t be found. Just like we did for the post content and for the Aside post format, we’ll place the message in a template part. Open no-results.php
, and add the following.
再回来看下index.php,你可以看到,如果数据库中存在文章,则主循环加载content.php。但如果没有文章存在会发生什么?如果不能找到帖子,就显示一条消息。就像我们在边栏post格里面做的那样,把消息放在模板片里。打开no-results.php,并添加以下代码。
1 <?php 2 /** 3 * The template part for displaying a message that posts cannot be found. 4 * 5 * Learn more: http://codex.wordpress.org/Template_Hierarchy 6 * 7 * @package Shape 8 * @since Shape 1.0 9 */ 10 ?> 11 <article id="post-0" class="post no-results not-found"> 12 <header class="entry-header"> 13 <h1 class="entry-title"><?php _e( 'Nothing Found', 'shape' ); ?></h1> 14 </header><!-- .entry-header --> 15 <div class="entry-content"> 16 <?php if ( is_home() && current_user_can( 'publish_posts' ) ) : ?> 17 <p><?php printf( __( 'Ready to publish your first post? <a href="%1$s">Get started here</a>.', 'shape' ), admin_url( 'post-new.php' ) ); ?></p> 18 <?php elseif ( is_search() ) : ?> 19 <p><?php _e( 'Sorry, but nothing matched your search terms. Please try again with some different keywords.', 'shape' ); ?></p> 20 <?php get_search_form(); ?> 21 <?php else : ?> 22 <p><?php _e( 'It seems we can’t find what you’re looking for. Perhaps searching can help.', 'shape' ); ?></p> 23 <?php get_search_form(); ?> 24 <?php endif; ?> 25 </div><!-- .entry-content --> 26 </article><!-- #post-0 .post .no-results .not-found -->
Not much different from content.php
and content-aside.php
. We even have a specialized message to display when no results turn up in a search (that’ll come in handy during the search.php
lesson).
Next, we have to include no-results.php
in index.php
. Openindex.php
and add the following, right after <?php shape_content_nav( 'nav-below' ); ?>
and before <?php endif>
.
content.php和content-aside.php没有太大的区别。我们甚至有一个专门的消息,显示在没有搜索结果时(在讲解search.php那一课时,这会派上用场)。
接下来,我们将no-results.php
包含在index.php中。 打开index.php并添加以下代码,在<?php shape_content_nav( 'nav-below' ); ?>
之后,<?php endif>之前。
1 <?php else : ?> 2 <?php get_template_part( 'no-results', 'index' ); ?>
Call up the sidebar and footer
One last thing and we’re done with index.php
. At the very end of the file, let’s call in the sidebar.php and footer.php templates with the following code.
完成了index.php的最后一个任务:在最末尾的文件,使用下面的代码调用 名为sidebar.php和footer.php的模板。
1 <?php get_sidebar(); ?> 2 <?php get_footer(); ?>
Here’s how the final index.php
file should look.
如下代码就是index.php文件最后的样子:
1 <?php 2 /** 3 * The main template file. 4 * 5 * This is the most generic template file in a WordPress theme 6 * and one of the two required files for a theme (the other being style.css). 7 * It is used to display a page when nothing more specific matches a query. 8 * E.g., it puts together the home page when no home.php file exists. 9 * Learn more: http://codex.wordpress.org/Template_Hierarchy 10 * 11 * @package Shape 12 * @since Shape 1.0 13 */ 14 get_header(); ?> 15 <div id="primary" class="content-area"> 16 <div id="content" class="site-content" role="main"> 17 <?php if ( have_posts() ) : ?> 18 <?php shape_content_nav( 'nav-above' ); ?> 19 <?php /* Start the Loop */ ?> 20 <?php while ( have_posts() ) : the_post(); ?> 21 <?php 22 /* Include the Post-Format-specific template for the content. 23 * If you want to overload this in a child theme then include a file 24 * called content-___.php (where ___ is the Post Format name) and that will be used instead. 25 */ 26 get_template_part( 'content', get_post_format() ); 27 ?> 28 <?php endwhile; ?> 29 <?php shape_content_nav( 'nav-below' ); ?> 30 <?php else : ?> 31 <?php get_template_part( 'no-results', 'index' ); ?> 32 <?php endif; ?> 33 </div><!-- #content .site-content --> 34 </div><!-- #primary .content-area --> 35 <?php get_sidebar(); ?> 36 <?php get_footer(); ?>