什么是子主题?子主题是一项有用的 WordPress 功能,它允许开发人员无需从头开始构建新模板,而是利用现有主题中已有的所有功能。
但是,有时,我们为网站选择的父主题可能具有一些我们不需要的功能(或者我们需要进行自定义以最适合我们的需求),例如自定义帖子类型使用不同的 slug、简码、JavaScript 库、我们不使用的图像大小等等...
两种方式自定义主题
虽然通过直接编辑主题可以很容易地实现我们想要的目标,但每次更新主题时我们都必须再次进行所有自定义。这可能会令人沮丧,因此还有另一种选择:我们可以创建一个子主题并使用>functions.php>文件来修改父主题 > 特点。这样我们就可以在每次发布新版本时升级父主题,而不会丢失我们的自定义内容。
在我们讨论更具体的细节之前,先简要说明一下主题外观:我们可以通过导入子主题的 style.css 文件来修改颜色、背景、排版和布局父 style.css 并覆盖我们想要更改的样式。
为了对布局进行更多控制,我们还可以按照 Abbas Suterwala 在他的帖子中的建议,并在子主题中克隆父自定义模板文件:
然后子主题可以选择覆盖其他模板文件,例如 author.php、category.php 等。WordPress 框架首先查找模板文件在子主题目录中,如果没有找到,将从父目录中获取它。
我们可以修改什么
通过子主题的functions.php文件我们可以处理:
- 主题功能
- 自定义帖子类型和分类
- 菜单和侧边栏
- 小部件
- 简码
- 其他图像尺寸
- 元框
- JavaScript 和 CSS
- 父主题操作和过滤器
那么,假设我们有这样的网站结构:
-
htdocs 或 www
-
wp-内容
-
主题
-
foo-theme(父主题的目录 - 它不会被修改)
- functions.php
- header.php
- style.css
- 其他模板文件...
-
foo-theme-child(子主题的目录)
- functions.php(我们将用来自定义父主题的文件)
- header.php(覆盖父主题的header.php)
- style.css(这是子主题中必需的文件,必须命名为style.css)
-
foo-theme(父主题的目录 - 它不会被修改)
-
主题
-
wp-内容
让我们开始吧:在 /wp-content/themes/foo-theme-child/ 目录中创建一个空的 functions.php 文件。
在大多数情况下,我们将使用通用的 wp_tuts_remove_features()
函数,挂钩到 WordPress after_setup_theme
操作。我们还将 10
设置为第三个参数(优先级),因此我们确定该函数在父函数之前触发。
add_action( 'after_setup_theme', 'remove_parent_theme_features', 10 );
function remove_parent_theme_features() {
// our code here
}
1.删除主题功能
一些父主题通过 add_theme_support
函数向 WordPress 添加功能。
可用功能有:
后格式
后缩略图
自定义背景
自定义标头
自动提要链接
所以要删除它们,我们可以修改functions.php文件中的remove_parent_theme_features()
函数。
function remove_parent_theme_features() {
remove_theme_support( 'post-formats' );
remove_theme_support( 'post-thumbnails' );
remove_theme_support( 'custom-background' );
remove_theme_support( 'custom-header' );
remove_theme_support( 'automatic-feed-links' );
}
2.删除自定义帖子类型和分类
删除自定义帖子类型和自定义分类法很简单:如果父 functions.php 文件通过 parent_movie_add_post_type()
函数添加 Movie 自定义帖子类型:
// PARENT functions.php
add_action( 'after_setup_theme', 'parent_movie_add_post_type' );
function parent_movie_add_post_type() {
$parent_args = array(
// other arguments...
'rewrite' => array( 'slug' => 'movie' ),
'supports' => array( 'title', 'editor', 'author', 'excerpt' )
);
register_post_type( 'movie', $parent_args );
}
...借助我们的子 functions.php 文件,我们可以自定义它:
'
// CHILD functions.php
function remove_parent_theme_features() {
// remove Movie Custom Post Type
remove_action( 'init', 'parent_movie_add_post_type' );
/*
alternatively, we can add our custom post type to
overwrite only some aspects of the parent function
*/
add_action( 'init', 'child_movie_post_type' );
}
function child_movie_post_type() {
$child_args = array(
// other arguments...
// change Custom Post slug
'rewrite' => array( 'slug' => 'child-movie' ),
// remove excerpts and add post thumbs
'supports' => array( 'title', 'editor', 'author', 'thumbnail' )
);
register_post_type( 'movie', $child_args );
}
我们还可以在不取消注册帖子类型的情况下仅删除某些特征,例如,如果我们想用帖子特色图像替换摘录字段,我们可以这样修改函数:
'
function remove_parent_theme_features() {
add_action( 'init', 'wp_tuts_remove_post_feature' );
}
function wp_tuts_remove_post_feature() {
// remove excerpt
remove_post_type_support( 'movie', 'excerpt' );
// add post thumbs
add_post_type_support( 'movie', 'thumbnail' );
}
您可以在 WordPress Codex 中的 remove_post_type_support
下找到可移除功能的完整列表。
与自定义帖子类型类似,您可以通过 parent_taxonomy()
函数删除在父主题中添加的自定义分类,方法如下:
function wp_tuts_after_setup_theme() {
remove_action( 'init', 'parent_taxonomy' );
}
3.删除菜单
我们可以通过 unregister_nav_menu()
函数删除父主题的菜单。该函数采用一个参数,即 register_nav_menu()
函数中使用的菜单位置标识符 slug。
如果父主题注册了标题菜单:
'
// PARENT functions.php
add_action( 'after_setup_theme', 'register_my_menu' );
function register_my_menu() {
register_nav_menu( 'header-menu', __( 'Header Menu' ) );
}
我们可以这样删除它:
'
// CHILD functions.php
function remove_parent_theme_features() {
unregister_nav_menu( 'header-menu' );
}
要识别已注册的菜单,我们可以在父主题代码中搜索 register_nav_menu()
调用。该函数的第一个参数代表我们可以用来取消注册的菜单 ID(在本例中为 header-menu
)。
4.删除小部件和侧边栏
WordPress 附带了一些我们可以停用的默认小部件。此外,我们的父主题可以添加自己的小部件,因此我们可以在主题文件中搜索它们的声明位置并记下它们的名称。通常它们在扩展 WP_Widget
类的 PHP 类中声明:
// PARENT theme
class ParentWidgetName extends WP_Widget {
// widget code
}
因此,要取消注册小部件,我们使用类名 ParentWidgetName
:
add_action( 'widgets_init', 'wp_tuts_parent_unregister_widgets', 10 );
function wp_tuts_parent_unregister_widgets() {
// remove (some) WordPress default Widgets
unregister_widget( 'WP_Widget_Pages' );
unregister_widget( 'WP_Widget_Calendar' );
// remove Parent registered Widget
unregister_widget( 'ParentWidgetName' );
// register a custom Widget (if needed)
register_widget( 'MyCustomWidget' );
}
// don't forget to add the Widget Class
class MyCustomWidget extends WP_Widget {
// Custom Widget code
}
对于侧边栏,操作类似:
'
add_action( 'widgets_init', 'wp_tuts_parent_unregister_sidebars', 10 );
function wp_tuts_parent_unregister_sidebars() {
// remove a sidebar registered by the Parent Theme
unregister_sidebar( 'first-footer-widget-area' );
}
要识别已注册的侧边栏,我们可以在父主题的代码中搜索 register_sidebar()
调用。
我们需要做的就是记下侧边栏 ID:
'
// PARENT functions.php
$args = array(
'id' => 'first-footer-widget-area',
// other args...
);
register_sidebar( $args );
5.删除短代码
覆盖或删除短代码很容易,我们只需要这样修改我们的函数:
'
function remove_parent_theme_features() {
// remove the parent [gmap] shortcode
remove_shortcode( 'gmap' );
// add our [gmap] shortcode
add_shortcode( 'gmap', 'child_shortcode_gmap' );
}
function child_shortcode_gmap( $atts ) {
// create our shortcode that overwrites the parent one
}
要识别已注册的短代码,我们可以在父主题代码中搜索 add_shortcode()
调用。第一个参数是我们要查找的参数;-)。
6.删除附加图像尺寸
如果父主题添加了我们不在子主题中使用的新图像尺寸,我们可以在父主题代码中搜索 add_image_size()
调用。在本例中,它们是:custom_size_parent_1
和 custom_size_parent_2
。我们通过这种方式重置它们:
add_filter( 'intermediate_image_sizes_advanced', 'remove_parent_image_sizes' );
function remove_parent_image_sizes( $sizes ) {
unset( $sizes['custom_size_parent_1'] );
unset( $sizes['custom_size_parent_2'] );
return $sizes;
}
这很有用,因为每次用户上传图像时,WordPress 都不会创建我们不使用的其他图像尺寸。
要创建自定义图像尺寸,我们可以将其添加到子 functions.php 文件中:
'
if ( function_exists( 'add_image_size' ) ) {
// 400 pixels wide and unlimited height
add_image_size( 'custom_size_child_1', 400, 9999 );
// 320 pixels wide and 240 px tall, cropped
add_image_size( 'custom_size_child_2', 320, 240, true );
}
7.删除元框
通过 remove_meta_box()
函数,我们可以删除默认的 WordPress 和父主题元框。
WordPress 默认元框列表可在 WordPress Codex 中的 remove_meta_box()
下找到。该函数具有三个参数:元框 ID、将从中删除的页面、编辑上下文(normal
、advanced
、side
)。
如果父主题在帖子编辑屏幕中添加了元框,我们可以通过以下方式禁用它们:
'
add_action( 'admin_menu' , 'wp_tuts_remove_metaboxes', 99 );
function wp_tuts_remove_metaboxes() {
// remove default WP Trackback Metabox from Posts editing page
remove_meta_box( 'trackbacksdiv', 'post', 'normal' );
// remove a Parent Theme Metabox 'parent_post_foo_metabox'
remove_meta_box( 'parent_post_foo_metabox', 'post', 'normal' );
}
我们可以通过在父主题代码中搜索 add_meta_box
或 add_meta_boxes()
调用来识别父元框。
要删除的元框的 ID 是 add_meta_box()
函数的第一个参数。
8. 删除 JavaScript 和 CSS 样式表
如果父主题添加了我们不需要的 JavaScript 和 CSS 样式:
'
// PARENT functions.php
add_action( 'wp_print_scripts', 'parent_scripts' );
add_action( 'wp_print_styles', 'parent_styles' );
function parent_scripts() {
wp_enqueue_script( 'fancybox-parent-js', get_stylesheet_directory_uri() . '/fancybox/jquery.fancybox.pack.js' );
}
function parent_styles() {
wp_enqueue_style( 'fancybox-parent-css', get_stylesheet_directory_uri() . '/fancybox/jquery.fancybox.css' );
}
我们可以这样删除它们:
'
// CHILD functions.php
add_action( 'wp_print_scripts', 'child_overwrite_scripts', 100 );
add_action( 'wp_print_styles', 'child_overwrite_styles', 100 );
function child_overwrite_scripts() {
wp_deregister_script( 'fancybox-parent-js' );
}
function child_overwrite_styles() {
wp_deregister_style( 'fancybox-parent-css' );
}
要识别已注册的 JavaScript 和 CSS 样式,我们可以在父主题代码中搜索 wp_enqueue_script()
和 wp_enqueue_style()
调用。
该函数的第一个参数是我们可以在 wp_deregister_script()
或 wp_deregister_style()
函数中使用的参数。
9.删除父主题操作和过滤器
某些主题(例如 Thematic)提供了多个挂钩来修改主题行为,而无需更改主题文件。在本例中,Thematic 提供了一个 thematic_header
操作来加载其他操作:
thematic_brandingopen()
thematic_blogtitle()
thematic_blogdescription()
thematic_brandingclose()
thematic_access()
我们不会详细研究这些函数的作用,可能其中一些函数会在博客标题中打印一些信息:名称、描述等等...在这种情况下,我们可以停用 thematic_blogdescription()
函数这样:
// Unhook default Thematic functions
function unhook_thematic_functions() {
// we put the position number of the original function (5)
// for priority reasons
remove_action( 'thematic_header', 'thematic_blogdescription', 5 );
}
add_action( 'init', 'unhook_thematic_functions' );
在这些情况下,可能很难理解父主题的结构及其工作原理。我的建议是选择一个带有详细文档、良好的支持论坛并在整个代码中提供钩子的父主题。
这肯定会让我们损失更少的开发时间,并使子主题的定制变得更加容易。
参考文献
- 子主题基础知识和在 WordPress 中创建子主题
-
WordPress Codex 文档
after_setup_theme
remove_action
add_theme_support
register_post_type
add_post_type_support
remove_post_type_support
register_nav_menu
unregister_nav_menu
register_widget
unregister_widget
register_sidebar
unregister_sidebar
add_shortcode
remove_shortcode
add_image_size
add_meta_box
remove_meta_box
wp_deregister_script
wp_deregister_style
- WordPress 父主题集合
- 专题主题框架