Home » Code » WordPress主题开发Part1——首页

WordPress主题开发Part1——首页

使用Wordpress(下面简称WP)写博客一年多,对它的了解其实还是很少。作为一个发展多年的老牌博客程序,它早已不是只能用来搭建博客写写文章这么简单。

WP强大的主题与插件机制背后,有成千上万内置的函数、钩子、类以及方法,对于不熟悉的人来说鼓捣起主题来一时还不真不知道如何下手。还好网络上有人做了一个最基本的主题(项目名叫underscores,Github有5500多Star),在它的基础上,辅以各种百度谷歌还是可以进行下去的。当然,官方的代码参考文档是必不可少的。

到underscores网站输入一个名字就可以生成主题压缩包,下载下来可以看到它包含了一个WP主题应该有的一些文件。

wp-theme-file
将这个主题文件上传到一个WP网站的主题目录,是可以正常启用的。只是样式神马的基本没有,但它确实是一个完整的WP主题,基本功能都是实现了的。咱们要做的就是按照自己要求添加CSS样式和其他功能。

引入CSS&Javascript文件

WP主题必不可以的一个style.css文件underscores已经帮我们生成了,它虽说是一个很基本的样式“重置”,但也有800多行。我们需要引入我们自己写的CSS&Javascript文件要如何操作呢? 假设我们的主题名称叫xigua,在functions.php函数文件中能找到xigua_scripts()这么一个函数,并且通过add_action()函数将它挂载到“wp_enqueue_scripts”这个钩子上边。官方文档显示“wp_enqueue_scripts”这个钩子Fires when scripts and styles are enqueued,字面意思是script文件和style文件入队后会被触发,姑且就简单记住要载入CSS和Javascript文件可以在这个钩子上挂载函数。

在这个xigua_scripts()内部,是通过wp_enqueue_style()函数将CSS文件入队,通过wp_enqueue_script()函数将Javascript文件入队。这两个函数用法按照里边已有的和查阅文档不难理解。

函数文件functions.php

一个主题函数必须的文件就两个:index.php和style.css。但这个函数文件一般是需要的,它在主题初始化时加载(包括前后台)。官方文档中指出它的作用主要是:

  1. 启用主题功能,例如:侧边栏,菜单,文章缩略图,文章格式,自定义标题栏。
  2. 定义用于模板文件中的函数。
  3. 设置一个选项菜单,让网站拥有者可以自定义颜色,样式,和你的主题的其他特性。

如果没有functions.php,你会发现后台的“外观”里边只有主题、自定义、编辑三项,没有小工具、菜单这两项。要添加这些,就得在functions.php里注册启用它们。如要有小工具,需要通过register_sidebar()注册一下,可以注册多个;提供原生的菜单,使用register_nav_menus(),也有可注册多个。另外,如果发现发表文章并没有什么标准、相册、链接之类的文章格式post_formats,也是因为没有没在初始化时启用它们,这时候需要add_theme_suport(),同样的你发现并不可以为文章添加特色图像,这时需要add_theme_support( ‘post-thumbnails’ )。

调试模式

关于调试模式,可以参考这里的文档说明。如要查看SQL语句,在配置文件中define(‘SAVEQUERIES’, true),之后就可以模板文件如footer.php中打印全局变量$wpdb->queries即可。

输出菜单

WP的菜单可以在后台随意编辑,非常方便。在模板中输出使用的是wp_nav_menu()这个函数,参数众多,基本可以满足需求,文档在这里。输出的HTML结构是div>ul>li>a。如果使用Bootstrap,你会发现WP输出的菜单结构跟Bootstrap的菜单结构出入较大,由其是在有二级菜单的时候,根本无法使用Bootstrap了。莫慌,这么“常规”的一个需求,肯定早有人遇到了,没错,我只是github的搬运工,一位名为twittem的网友已经为我们写好了walker类以便生成Bootstrap结构的菜单,点此查看下载使用吧。

2015-10-25补充:twittem这个walker类可能漏了一点,就是二级菜单项是当前菜单项时并没有为其父菜单也添加“active”样式类,解决方案也简单,将类文件68和69两行复制追加到69行之后,并将“current-menu-item”改为“current-menu-parent”即可。这样子菜单和父菜单就都有了”active”样式类。另外,当有子级菜单时父菜单并不会添加href值,在87行将下边else的复制上来即可。

2015-10-27补充:

想获得所有菜单项,首先获取所有位置的菜单信息,$locations = get_nav_menu_locations(),菜单信息数组中元素的键是在functions.php中通过register_nav_menu()注册菜单时的参数一,一般为”Primary”,表示主菜单。这时,获得菜单ID就是$menuID = $locations[‘Primary’],$menuObj = wp_get_nav_menu_object($menuID),得到菜单对象,$menuItems = wp_get_nav_menu_items($menuObj->item_id)即得到所有菜单项对象。

自定义查询

这个是关键。可以参考这篇这里以及这里。参考一中的文章很清楚的说明了四种进行自定义查询的方法,参考二则是官方对第2种使用WP_Query类的的详细说明。这里要注意“ignore_sticky_posts”这个参数,忽略置顶,默认是0不忽略。我在只获取全局最新的一篇文章时,使用posts_per_page=1&paged=1居然出来两篇文章,原来第一篇是置顶的,第二篇是最新的。将其置为1即可。这时最新的同时也是置顶也是能出来的。

2015-10-26补充:

一、默认情况下,直接使用while(have_posts()) : the_post(),取的是默认主查询的数据,也就是查询的最新发表的文章,越新发表越靠前,取的数量是后台中设置的。每次while循环后必须调用wp_reset_postdata()重置保存标签函数数据的全局变量!否则标签函数会错误失效!

二、使用query_posts(string query_string)注意不是下边说的get_posts,参数是字符串非数组。这个直接使用的主查询对象,并且会改变主查询,用法同一中是一样的。这时循环输出后同样的进行wp_reset_postdat(),还建议wp_reset_query()重置一下主查询。官方说法在一个query_posts()后再进行另一个query_posts(),可能会有不可预知的问题,建议调用此函数重置。

三、使用get_posts(array $args)注意不是上边说的query_posts,参数是数组不是字符串。这个也是使用的主查询对象,但它不会改变主查询,只返回一个二维数组,而且我们无法使用while(have_posts() : the_post()来循环以及使用标签函数。要循环可以直接foreach($result as $post),在循环内部调用setup_postdata($post)来为标签函数准备数据,这样就可以使用标签函数了。注意:循环变量必须是全局变量$post,换成其他是不成的!!!

四、使用new WP_Query(array $args)重新创建一个查询对象,下面有补充使用方法。

就上边补充里说的这三种添加自定义查询的方法,要如何选择呢?官方说法是建议使用三、四,不建议使用二。我测试二的sql语句要比三、四多出一条,而看上去三要多调用函数,四则要多生成对象。就着sql更慢的原则,还是按官方说法的使用三、四,当然个人更喜欢四——直接new多一个对象出来。

输出置顶文章

WP自带文章置顶功能,其实它是将置顶文章的ID存到options表里边,key为sticky_posts,要输出时,先用get_options(‘sticky_posts’)得到置顶文章的ID数组,再使用自定义查询,在查询参数中使用”post__in => ID数组”参数来查询即可。

输出文章基本信息

在首页输出文章列表时,一般都是在循环内部使用标签函数进行文章信息的输出,如the_title()输出标题、get_permalink()获得文章详情的链接等。开启循环一般是这么一段:

<?php if (have_posts()):?>
<?php while (have_posts()) : the_post();?>

/*各种HTML代码与标签函数嵌套输出一篇文章的信息*/

<?php endwhile;?>
<?php endif;?>

以上其实是针对主循环,也就是使用的是$wp_query这个默认的查询对象。如果我们使用new WP_Query()创建额外的查询对象,使用have_posts()、the_posts()时需要将查询对象写上,否则这两个函数还是调用的默认的查询对象$wp_query。

<?php $my_query = new WP_Query('p=7')?>
<?php if ($my_query->have_posts()):?>
<?php while ($my_query->have_posts()) : $my_query->the_post();?>

/*各种HTML代码与标签函数嵌套输出一篇文章的信息*/
/*内部标签函数则不需要写$my_query,跟循环主循环写法一致*/

<?php endwhile;?>
/*一个额外查询循环完后,别忘了调用一下这个函数重置一下,以便下个循环能正常使用标签函数*/
<?php wp_reset_postdata();?>
<?php endif;?>

输出摘要

WP输出摘要的标签函数是the_excerpt()。它首先检索一篇文章有没有手工添加了摘要(在发表文章下边可以手工添加的,如没有从顶端的显示选项中打开),如有手工摘要直接返回这部分的内容。如没有,再在文章内容中检索“More”标签,这在WP自带编辑器的功能按钮中有。如果有,将“More”标签前边的内容即为摘要。如果还是没有,将自动从文章内容截取前边55个字(一个中文字一个英文单词均算一个)作为摘要。摘要末尾还会默认加上“[…]”这个字符串。字数55以及末尾添加的字符都可以更改,方法是通过add_filter为Hook添加回调函数,详见官方说明。关于摘要的信息还可以参考这里

输出某一分类的文章

要是做一些门户新闻类的网站,这个应该是很常规的一个需求了。有了自定义查询,输出每个分类就进行一次查询然后循环输出之是可以解决的,但如果要是输出10个分类的文章,这个过程难道进行10次么?多次查询可能有数据库方面的压力,但这10个分类不同分类要显示的数量可能不一致,而且分类间要排序分类内还要按时间或其他来排序,一次查出基本是不可能的,再说还得使结果能正常的使用标签函数输出,这样子一想还是分10次查询来得方便(多想了)。在循环中常用的一些标签函数:

  • 获得当前文章的ID,$postID = get_the_ID();
  • 获得当前文章查看链接,get_permalink();
  • 获得当前文章标题,get_the_title();
  • 获得当前文章所属分类,$categories = get_the_category(),如同时属于多个分类,数组内部元素的顺序跟你查看分类目录从上到下看到的是一样的。假设其中某项为$category,则其ID为$category->term_id,其名称为$category->name,其别名为$category->slug,其父分类ID为$category->parent;
  • 获得某分类的名称,$catName = get_the_category_by_ID($catID);
  • 获得某分类的存档链接,get_category_link($catID);
  • 获得当前文章发表时间戳,get_the_time(),当前文章发表格式化后的日期时间,get_the_date();
  • 获得当前文章最近修改时间,get_the_modified_time(),当前文章最近修改格式化后的日期时间,get_the_modified_date();
  • 获得当前文章作者信息,get_the_author_meta(),会返回作者的各种信息,如只需要作者ID,get_the_author_meta(‘ID’),另外,get_the_author()会直接返回作者名称;
  • 获得某作者存档链接,get_author_post_url($authorID);
  • 获得当前文章特色图像,get_the_post_thumbnail(),返回一个HTML img标签。

One comment

Leave a Reply

Your email address will not be published. Required fields are marked *

*

Time limit is exhausted. Please reload CAPTCHA.