WordPress开发教程(三)之开发主题

这篇博客介绍如何开发一个简单的WordPress主题,以及构成主题的相关文件。

WordPress主题是一系列文件,在底层统一的设计下,共同协作来构建一个图形化界面。简单地说,主题为你的网站提供了皮肤,允许你修改内容展示的方式。

在这篇教程中,我们将学习主题开发。首先了解组成主题的基本文件,接着学习模板,模板标签和循环。

开始学习

主题通常存放在wp-conent/themes目录中。如果进入到那个目录,你会发现里面已经有了几个主题,那是默认的WordPress主题。

下面让我们来创建一个新的主题:

  • themes目录下创建文件夹,命名为my-awesome-theme
  • 在新的文件夹里,创建两个文件:style.cssindex.php

打开样式表文件,粘贴下面的代码 官方实例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/*
Theme Name: Awesome Theme
Theme URI: http://somethingaboutchina.com
Author: wcshinestar
Author URI: https://antmoving.github.io
Description: Awesome Theme brings your site to life with immersive featured images and subtle animations. With a focus on business sites, it features multiple sections on the front page as well as widgets, navigation and social menus, a logo, and more. Personalize its asymmetrical grid with a custom color scheme and showcase your multimedia content with post formats. Our default theme for 2017 works great in many languages, for any abilities, and on any device.
Version: 1.0
License: GNU General Public License v2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Text Domain: my-awesome-theme
Tags: one-column, two-columns, right-sidebar, flexible-header, accessibility-ready, custom-colors, custom-header, custom-menu, custom-logo, editor-style, featured-images, footer-widgets, post-formats, rtl-language-support, sticky-post, theme-options, threaded-comments, translation-ready
This theme, like WordPress, is licensed under the GPL.
Use it to make something cool, have fun, and share what you've learned with others.
*/

上面的信息会自动填充WordPress后台的Appearance > Theme页面中的”主题详情”部分。上面的评论中必须要包含主题的名字(其它是可选的,但是推荐填完所有信息)。注意:text Domain必须要准确匹配文件夹的名字(本例子中是my-awesome-theme)。

现在如果你导航到Appearance -> Themes部分,应该可以看到你的主题出现在列表中,甚至可以启动它。

模板的工作原理

WordPress主题使用模板文件进行工作的,它实际上是很巧妙的方法,与普通的HTML网站比较,它减少了网站运行需要的文件数量。如果你有一个HTML网站,对于每篇发表的文章都需要一个文件;而每个文件包含网站的头部(header),侧边栏(sidebar)和尾部(footer),对于每个文件来说,这都是相同的;唯一的不同之处是文章的内容。

因为PHP是在服务端处理的,我们可以更好地节约文件占有的空间。我们可以只拥有一个文件(模板文件),检测到所在的页面,要求PHP根据实际的文章标题和内容来取代占位符。

下面使用伪代码来展示如何工作的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<!DOCTYPE html>
<html>
<head>
<title>A single post template</title>
</head>
<body>
<div id="site-header">
<h1>Welcome to my site</h1>
<nav>
<ul>
<li><a href=''>Home</a></li>
<li><a href=''>About</a></li>
<li><a href=''>Contact</a></li>
</ul>
</nav>
</div>
<div id="article">
<h2 class="article-title"><?php the_title() ?></h2>
<div class="article-content"><?php the_content() ?></div>
<div class="article-meta">Published on <?php the_time( "Y-m-d" ) ?> by <?php the_author() ?></div>
</div>
<div id="site-footer">
<nav>
<ul>
<li><a href=''>Home</a></li>
<li><a href=''>About</a></li>
<li><a href=''>Contact</a></li>
</ul>
</nav>
<div id="copyright">&copy; Daniel Pataki</div>
</div>
</body>
</html>

在文章区域没有进行任何的硬编码,the_title()函数负责输出题目。这些函数检测到当前请求的文章,在数据库中查询正确的信息。

这样,网站的所有文章只需创建一个文件。许多系统,包括WordPress,都采取这样的方式,将网站的头部和尾部分离开。实际上,管理文章的文件更有可能像下面这样:

1
2
3
4
5
6
7
8
9
10
11
12
<?php get_header() ?>
<div id="article">
<h2 class="article-title"><?php the_title() ?></h2>
<div class="article-content"><?php the_content() ?></div>
<div class="article-meta">Published on <?php the_time( "Y-m-d" ) ?> by <?php the_author() ?></div>
</div>
<?php get_sidebar() ?>
<?php get_footer() ?>

主题的工作原理

我们将在主题中使用一些模板文件来搭建网站。我们要清楚为哪些页面创建哪些文件,这是由WordPress的模板层次管理的,让我们来看下页面的类型:

  • Archive页面:category archives, date archives, tag archives, author archives

  • Single页面:single posts, single pages, single custom post types

  • Front页面和Index页面

  • 错误页面

  • 搜索结果页面

它称作层次,因为WordPress在决定显示某个特定的内容时,会进行寻找一系列文件。下面来看个例子:

如果我们查看一个作者的归档页面,WordPress会检查在主题文件夹下是否存在名字是author-wflytoc.php的文件。如果存在,则使用;否则的话,WordPress会寻找包含作者ID的文件;假设ID是520,则使用的文件会是author-520.php;如果该文件也不存在,则WordPress会使用author.php文件;如果也不存在,则会使用archive.php文件;如果还不存在,则使用index.php(该文件是必须要存在的)。

注意,WordPress一开始会寻找具体的文件,接着是一般的文件。这样的话,你可以创建一个文件(author.php)来处理所有的作者;但是可以使用author-wflytoc.php来让特定的作者展示的不同。

构建主题

当构建新主题时,首先构建一个框架,也就是说先创建header和footer部分。

到目前为止,我们创建了一个新的主题,里面包含了空的index.php文件和一个样式表。

创建一个屏幕截图,这用来在WordPress后台的Appearance -> Themes页面对主题的展示。需要将图片裁剪成880px宽,660px高;命名为screenshot.png;将其放在主题目录下。

下一步创建主题的HTML框架,这包括所有页面都需要加载的代码,例如头部元素等。

首先创建header.php文件,将下面的代码粘贴到里面:

1
2
3
4
5
6
7
8
9
10
11
<!DOCTYPE html>
<html <?php language_attributes(); ?> class="no-js">
<head>
<meta charset="<?php bloginfo( 'charset' ); ?>">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="profile" href="http://gmpg.org/xfn/11">
<?php wp_head(); ?>
</head>
<body <?php body_class(); ?>>

创建footer.php文件,粘贴下面的代码:

1
2
3
4
<?php wp_footer() ?>
</body>
</html>

这里需要指出两个重要的函数:wp_head()wp_footer()。你应当记住:制作主题时,必须在</head>前放上wp_header();在</body>前放上wp_footer();这些作为标志帮助WordPress和插件正确地注入功能到你的主题中。

开始转向index.php文件;如果现在浏览网站的话,它是个空的屏幕。因为index.php文件是空的,header.phpfooter.php文件没有被使用。

添加下面的代码到index.php文件中:

1
2
3
4
5
6
<?php get_header() ?>
My Awesome Theme
<?php get_footer() ?>

下面来为主题添加样式,因为样式表不会被自动地加载。在创建HTML网站时,通常是在头部进行添加样式;在主题中永远不要这样做,应该让WordPress来处理它。

创建functions.php文件,添加下面的代码:

1
2
3
4
5
6
<?php
add_action( 'wp_enqueue_scripts', 'mat_assets' );
function mat_assets() {
wp_enqueue_style( 'my-awesome-theme', get_stylesheet_uri() );
}

要记住WordPress是如何将功能注入到主题中的,它操作的其中一个位置是在wp_head()函数中。上述的functions.php文件告诉WordPress关于我们的样式表,它会在头部添加正确的代码。

下面我们来创建一个可视化的框架:网站标题和内容盒子。在header.php文件中添加标题,开启内容盒子;在footer.php文件中,关闭内容盒子,并添加尾部的copyright文字;最后,在样式表中添加一些样式。

header.php文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!DOCTYPE html>
<html <?php language_attributes(); ?> class="no-js">
<head>
<meta charset="<?php bloginfo( 'charset' ); ?>">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="profile" href="http://gmpg.org/xfn/11">
<?php wp_head(); ?>
</head>
<body <?php body_class(); ?>>
<div id="site-header">
<h1><?php bloginfo('title') ?></h1>
</div>
<div id="site-content">

footer.php文件:

1
2
3
4
5
6
7
8
</div>
<div id="site-rooter">
<p>&copy;My Awesome Theme</p>
</div>
<?php wp_footer() ?>
</body>
</html>

style.css文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
html {
height: 100%;
background:#444;
font-family: "Helvetica Neue", Arial, sans-serif;
line-height: 1.5em;
}
#site-header {
text-align: center;
}
#site-header h1 {
font-size:32px;
color: #ffffff;
font-weight: 300;
letter-spacing: 1px;
}
#site-content {
max-width:625px;
background: #fff;
margin: 0 auto;
padding: 22px;
border-radius:5px;
}
#site-footer {
color: #fff;
text-align:center;
font-size:12px;
text-transform: uppercase;
}

除此之外,向index.php文件中添加一些内容。现在,参观网站的任何页面都将呈现相同的内容,因为目前只有index.php文件,它是所有页面的”退却文件(WordPress会为用户访问的页面寻找正确的文件来使用,寻找的过程是具有层级性的,最后会退却到index.php文件)”

理解WordPress的循环(Loop)

循环是几乎所有WordPress页面的核心,包含了页面上展示的内容。WordPress从URL中获取每个页面需要包含哪些内容。例如,单篇博客页面应该包含一篇博客内容;主页面应该包含几篇最近的博客;分类归档页面应该包含几篇该类别下的最近的博客。

信息是从数据库中自动抓取下来的,所要做的就是循环遍历获取到的所有文章。将下面代码粘贴到index.php文件:

1
2
3
4
5
6
7
8
9
10
11
<?php if( have_posts() ) : ?>
<?php while( have_posts() ) : the_post() ?>
<h2><a href='<?php the_permalink() ?>'><?php the_title() ?></a></h2>
<div class="content">
<?php the_content() ?>
</div>
<?php endwhile ?>
<?php else : ?>
<p>Oh No, there are no posts!</p>
<?php endif ?>

你将看到一系列文章出现到网站首页,如果点击文章的标题,文章的详情页面就会展示,尽管还没有为单篇文章创建对应的使用文件。

if语句用来检查have_posts()函数的值,如果有文章显示,则返回true;如果没有文章显示,则返回false。从else语句部分可以看出,如果没有文章,则展示一段文本。

如果有文章显示,则创建while循环,只要have_posts()返回true,循环体就会执行。使用的第一个函数是the_post(),会搭建文章的一些数据,并在内部进行计数。

展示文章时,上面的代码仅仅添加了标题和文章的完整内容。使用the_permalink()函数获取文章的URL;使用the_title()函数获取标题;使用the_content()函数获取文章的完整内容。这些类型的函数叫作模板标签,可以使用在循环中。

模板和if语句

如果想要在首页中展示文章的摘要,可以有两种选择:使用条件标签和创建新的模板文件。

WordPress的条件标签可以用来检查各种东西,例如,你可以检查当前所在的页面是否时单篇文章页面。

is_singular()标签可以完成下面的任务:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php get_header() ?>
<?php if( have_posts() ) : ?>
<?php while( have_posts() ) : the_post() ?>
<h2><a href='<?php the_permalink() ?>'><?php the_title() ?></a></h2>
<div class="content">
<?php if( is_singular() ) : ?>
<?php the_content() ?>
<?php else : ?>
<?php the_excerpt() ?>
<?php endif ?>
</div>
<?php endwhile ?>
<?php else : ?>
<p>Oh No, there are no posts!</p>
<?php endif ?>
<?php get_footer() ?>

另一种途径是使用两个单独的文件:index.php包含显示摘要的多篇文章;而single.php展示完整的内容。创建single.php文件,在循环中使用the_content()

看一下修改过的index.php文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php get_header() ?>
<?php
if( have_posts() ) {
while( have_posts() ) {
the_post();
get_template_part( 'template-parts/content', '' );
}
}
else {
get_template_part( 'template-parts/content', 'none' );
}
?>
<?php get_footer() ?>

上面代码中,将文章的内容放在不同的文件中,get_template_part()函数用于抓取文件中的内容;第二个参数与第一个参数使用-连接,构成一个路径;else语句中,函数将会调用template-parts/content-none.php。在if语句中,第二个参数是空的字符串,所以这将调用template-parts/content.php

single.php文件中,添加相同的代码,但是使用single作为get_template_part()函数的第二个参数。

最后,创建template_parts文件夹,和三个文件:content.php,content-none.phpcontent-single.php;并将相关的代码粘贴到对应的文件中,比如,content.php文件中的代码如下:

1
2
3
4
5
<h2><a href='<?php the_permalink() ?>'><?php the_title() ?></a></h2>
<div class="content">
<?php the_excerpt() ?>
</div>