子主题

子主题允许你更改站点外观的小方面,但仍保留主题的外观和功能。为了理解子主题是如何工作的,首先必须理解父主题和子主题之间的关系。

什么是父主题

父主题是一个完整的主题,包括主题工作所需的所有WordPress模板文件和资产。所有主题(不包括子主题)都被视为父主题。

 

什么是子主题

正如概述中所指出的,子主题继承了父主题的外观及其所有功能,可以用来修改主题的任何部分。通过这种方式,自定义的内容与父主题的文件是分开的。使用子主题可以让你升级父主题而不影响你对网站进行的定制。

子主题:

  • 使你的修改可移植、可复制
  • 将自定义与父主题功能分开
  • 允许更新父主题而不破坏你的修改
  • 允许你利用其将努力和测试投入到父主题
  • 节省开发时间,因为您不需要重新造轮子
  • 是开始学习主题开发的好方法。
如果你要进行广泛的自定义(除了样式和一些主题文件之外)创建一个父主题可能是更好的选择。创建父主题可以避免将来出现不推荐使用的代码问题,这需要根据具体的情况来决定。

 

如何创建子主题

 

1. 创建子主题文件夹

首先,在主题目录中创建一个新文件夹,位于wp-content/themes

这个目录需要一个名字,最好的做法是给子主题起一个与父主题相同的名字,但在后面加上-child。例如,如果你要建一个twentyfifteen的子主题,那么这个目录将被命名为twentyfifteen-child

 

2. 创建样式表:style.css

接下来,你需要创建一个名为style.css的样式表文件,它将包含控制主题外观的所有CSS规则和声明。样式表必须在文件的最顶端包含以下所需的头部注释,这将告诉WordPress关于这个主题的基本信息,包括它是一个具有特定父主题的子主题。

/*
 Theme Name:   Twenty Fifteen Child
 Theme URI:    http://example.com/twenty-fifteen-child/
 Description:  Twenty Fifteen Child Theme
 Author:       John Doe
 Author URI:   http://example.com
 Template:     twentyfifteen
 Version:      1.0.0
 License:      GNU General Public License v2 or later
 License URI:  http://www.gnu.org/licenses/gpl-2.0.html
 Tags:         light, dark, two-columns, right-sidebar, responsive-layout, accessibility-ready
 Text Domain:  twentyfifteenchild
*/

需要以下信息:

  • Theme Name – 你的主题所特有的名称。
  • Template – 父主题目录的名称。本例中,父主题是Twenty Fifteen,所以Template将是tentyfifteen。根据实际情况而定。

添加其余适用的信息,唯一需要的子主题文件是style.css,但functions.php是引入样式所必须的(如下)

 

3. 引入样式表

最后一步,是引入父主题和子主题的样式表(如果需要)。

在过去,常见的方法是在style.css中使用@import来导入父主题的样式表。这不再是推荐的做法,因为它增加了样式表的加载时间。另外,父样式表也有可能被加载两次。

样式表引入的理想方式是由父主题同时加载(父主题的和子主题的),但并非所有主题都这样做。因此,你需要检查父主题的代码,看看它做了什么,并获得父主题使用的句柄名称,该句柄是wp_enqueue_style()的第一个参数。

有几件事需要记住:

  • 子主题在父主题之前加载。
  • 所有内容都与一个有优先级的动作挂钩(默认是10),但具有相同优先级的动作按加载顺序运行。
  • 对于每个句柄,只有对wp_enqueue_style()的第一次调用是相关的(其他的被忽略)。
  • wp_enqueue_style()的依赖性参数会影响加载顺序。
  • 如果没有版本号,网站访问者将得到他们的浏览器所缓存的内容,而不是新版本。
  • 使用函数获取主题的版本,将返回已启用主题的版本(如果有子级,则返回子级)。
  • 名为get_stylesheet*的函数首先寻找子主题,然后再寻找父主题。

引用样式的推荐方式是在子主题的functions.php中添加一个wp_enqueue_scripts动作并使用wp_enqueue_style()()。
如果没有,请在子主题目录下创建一个functions.php。子主题的functions.php的第一行将是一个开放的 PHP 标签(<?php),之后你可以根据父主题的做法来写 PHP 代码。

如果父主题加载了两个样式表,子主题就不需要做任何事情。

如果父主题使用以get_template开头的函数加载其样式,比如get_template_directory()get_template_directory_uri(),子主题只需要加载子样式,在依赖参数中使用父主题的句柄。

add_action( 'wp_enqueue_scripts', 'my_theme_enqueue_styles' );
function my_theme_enqueue_styles() {
    wp_enqueue_style( 'child-style', get_stylesheet_uri(),
        array( 'parenthandle' ), 
        wp_get_theme()->get('Version') // this only works if you have Version in the style header
    );
}

如果父主题使用以get_stylesheet开头的函数加载其样式,例如get_stylesheet_directory()get_stylesheet_directory_uri(),子主题需要同时加载父和子样式表。请确保使用与父主题相同的句柄名称来处理父主题的样式。

add_action( 'wp_enqueue_scripts', 'my_theme_enqueue_styles' );
function my_theme_enqueue_styles() {
    $parenthandle = 'parent-style'; // This is 'twentyfifteen-style' for the Twenty Fifteen theme.
    $theme = wp_get_theme();
    wp_enqueue_style( $parenthandle, get_template_directory_uri() . '/style.css', 
        array(),  // if the parent theme code has a dependency, copy it to here
        $theme->parent()->get('Version')
    );
    wp_enqueue_style( 'child-style', get_stylesheet_uri(),
        array( $parenthandle ),
        $theme->get('Version') // this only works if you have Version in the style header
    );
}

 

4. 安装子主题

像安装任何其他主题一样安装子主题。你可以使用FTP将文件夹复制到网站上,或者创建一个子主题文件夹的压缩文件,选择保持文件夹结构的选项,然后点击外观>主题>添加新主题来上传这个压缩文件。

 

5. 启用子主题

你的子主题现在可以启用了。登录你的网站进入管理界面>外观>主题。你应该看到你的子主题被列出了,并准备好启用。如果你的WordPress安装是支持多站点的,那么你可能需要切换到你的网络管理界面来启用这个主题(在网络管理界面的主题标签中)。然后你可以切换回你的特定站点的WordPress管理界面来启用你的子主题。

你可能需要在启用子主题后从外观>菜单和主题选项(包括背景和页眉图像)中重新保存你的菜单。

 

添加模板文件

除了functions.php文件(如上所述),你添加到子主题的任何文件都会覆盖父主题中的相同文件。

在大多数情况下,最好从父主题中复制一个你想改变的模板文件进来,然后在复制的文件中进行修改,不改变父文件。例如,如果你想改变父主题的header.php文件的代码,你可以将该文件复制到你的子主题文件夹,并在那里进行定制。

有几个插件可以让你检测你正在浏览的页面上使用的是什么特定模板。

你也可以在子主题中包含不包含在父主题中的文件。例如,你可能想创建一个比父主题更具体的模板,如一个特定的页面或分类归档的模板(例如,page-3.php将为一个ID为3的页面加载)。

有关WordPress如何确定使用哪个模板的更多信息,请参阅模板层次结构页面。

 

使用 functions.php

style.css不同,子主题的functions.php不会覆盖父主题的对应部分。相反,它是在父主题的 functions.php之外被加载的。(具体来说,它被加载在父主题的文件之前)。

这样一来,子主题的 functions.php 就为修改父主题的功能提供了一个聪明、省事的方法。假设你想给主题添加一个PHP函数。最快的方法是打开它的functions.php文件,把函数放在那里。但这并不聪明:下次你的主题被更新时,你的函数就会消失。但有一个聪明的替代方法:你可以创建一个子主题,在其中添加一个 functions.php 文件,并在该文件中添加你的函数。这个函数在那里也会做完全一样的工作,好处是它不会被父主题的未来更新所影响。不要把父主题的 functions.php 的全部内容复制到子主题的 functions.php 中。

functions.php的结构很简单。顶部是一个开放的 PHP 标签,下面是你的一些 PHP 代码。在这个文件中,你可以根据自己的意愿放入很多或很少的函数。下面的例子显示了一个基本的 functions.php 文件,它只做了一件简单的事情:在 HTML 页面的头部元素上添加一个 favicon 链接。

<?php // Opening PHP tag - nothing should be before this, not even whitespace

// Custom Function to Include
function my_favicon_link() {
    echo '<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />' . "\n";
}
add_action( 'wp_head', 'my_favicon_link' );

子主题的functions.php首先被加载,这意味着你可以通过有条件的声明,使你的主题的用户函数具有可插拔性,也就是说,可以被子主题替换。

if ( ! function_exists( 'theme_special_nav' ) ) {
    function theme_special_nav() {
        //  Do something.
    }
}

这样一来,子主题就可以通过简单的事先声明来取代父主题的一个PHP函数。

关于在子主题的 functions.php 文件中包含哪些内容的更多信息,请阅读主题函数页面。

 

引用或包含其他文件

当你需要包含位于子主题目录结构中的文件时,你将需要使用get_stylesheet_directory()。由于style.css在子主题的根目录下,get_stylesheet_directory()指向子主题的目录(而不是父主题的目录)。要引用父主题的目录,你可以用get_template_directory()来代替。

下面的例子,说明在引用存储于子主题目录下的文件时如何使用get_stylesheet_directory()

<?php require_once( get_stylesheet_directory(). '/my_included_file.php' ); ?>

这个例子使用get_stylesheet_directory_uri()来显示存储在子主题目录下/images文件夹中的图片。

<img src="<?php echo get_stylesheet_directory_uri(); ?>/images/my_picture.png" alt="" />

get_stylesheet_directory()返回文件路径不同,get_stylesheet_directory_uri()返回一个URL,这对前端资源很有用。

 

引入样式和脚本

脚本和样式应该用它们自己的函数来引入,然后这些应该被包裹在一个动作中。欲了解更多信息,请阅读引入CSS和JavaScript页面。

WordPress不会在前端自动加载子主题的样式表。下面是一个使用wp_enqueue_scripts()动作钩子来调用函数的例子,这个函数可以引入主题的样式表。

<?php
add_action( 'wp_enqueue_scripts', 'my_plugin_add_stylesheet' );
function my_plugin_add_stylesheet() {
    wp_enqueue_style( 'my-style', get_stylesheet_directory_uri() . '/style.css', false, '1.0', 'all' );
}

 

特别注意事项

 

文章格式

子主题会继承父主题所定义的文章格式。但在创建子主题时,要注意使用add_theme_support('post-formats')将覆盖父主题所定义的格式,而不是添加到它上面。

 

RTL 支持

为了支持RTL语言,在你的子主题中添加一个rtl.css文件,包含:

/*
Theme Name: Twenty Fifteen Child
Template: twentyfifteen
*/

即使父主题没有rtl.css文件,我们也建议将rtl.css文件添加到你的子主题中。WordPress只有在is_rtl()为true时才会自动加载rtl.css文件。

 

国际化

子主题可以通过使用WordPress的国际化API来翻译成其他语言。关于子主题的国际化,有一些特殊的考虑。

要使一个子主题国际化,请遵循以下步骤:
1. 添加languages目录

  • 例如:twentyfifteen-child/languages/

2. 添加语言文件

  • 你的文件名必须是he_IL.pohe_IL.mo(取决于你的语言),不像插件文件是domain-he_IL.xx

3. 载入textdomain(文本域)

  • functions.php中使用load_child_theme_textdomain()在after_setup_theme动作中。
  • load_child_theme_textdomain()中定义的文本域应该被用来翻译子主题中的所有字符串。

4. 使用GetText函数来为你的字符串添加国际化支持

 

示例:textdomain

<?php
/**
  * Set up My Child Theme's textdomain.
  *
  * Declare textdomain for this child theme.
  * Translations can be added to the /languages/ directory.
  */
function twentyfifteenchild_theme_setup() {
    load_child_theme_textdomain( 'twentyfifteenchild', get_stylesheet_directory() . '/languages' );
}
add_action( 'after_setup_theme', 'twentyfifteenchild_theme_setup' );

在这一点上,子主题中的字符串已经准备好进行翻译。为了确保它们被正确地国际化以进行翻译,每个字符串都需要有twentyfifteenchild文本域。

 

示例:gettext 函数

这里有一个输出“代码如诗”的例子。

<?php
esc_html_e( 'Code is Poetry', 'twentyfifteenchild' );
?>

load_child_theme_textdomain()中定义的文本域应该被用来翻译子主题中的所有字符串。如果父主题的模板文件被包含在内,文本域应该从父主题中定义的文本域变为子主题中定义的文本域。