自定义API是面向对象的,有四种主要的定制器对象类型:面板(Panels)、板块(Sections)、设置(Settings)和控件(Controls)。设置将UI元素(控件)与保存在数据库中的设置联系起来。板块是控件的UI容器,以改善其组织。面板是将多个板块组合在一起的容器。
每个定制器对象都由一个PHP类表示,所有的对象都由定制器管理(Customize Manager)对象(WP_Customize_Manager)管理。
要添加、删除或修改任何定制器对象,以及访问定制器管理,请使用customize_register
钩子。
function themeslug_customize_register( $wp_customize ) { // Do stuff with $wp_customize, the WP_Customize_Manager object. } add_action( 'customize_register', 'themeslug_customize_register' );
定制器管理为每个定制器对象类型提供 add_, get_, 和 remove_ 方法,每个方法都与一个id一起工作。get_ 方法允许直接修改添加控件时指定的参数。
add_action('customize_register','my_customize_register'); function my_customize_register( $wp_customize ) { $wp_customize->add_panel(); $wp_customize->get_panel(); $wp_customize->remove_panel(); $wp_customize->add_section(); $wp_customize->get_section(); $wp_customize->remove_section(); $wp_customize->add_setting(); $wp_customize->get_setting(); $wp_customize->remove_setting(); $wp_customize->add_control(); $wp_customize->get_control(); $wp_customize->remove_control(); }
注意:主题一般不应该用 get 方法修改核心板块和面板,因为主题不应该修改核心的、与主题无关的功能。我们鼓励插件在必要时使用这些功能。主题不应该"重新组织"不是由主题添加的定制器板块。
设置
设置(Settings)处理实时预览、保存和净化你的定制器对象。每个设置都由一个控件对象管理,在添加一个新的设置时,有几个参数可用。
$wp_customize->add_setting( 'setting_id', array( 'type' => 'theme_mod', // or 'option' 'capability' => 'edit_theme_options', 'theme_supports' => '', // Rarely needed. 'default' => '', 'transport' => 'refresh', // or postMessage 'sanitize_callback' => '', 'sanitize_js_callback' => '', // Basically to_json. ) );
重要提示:不要使用类似 widget_*
、sidebars_widgets[*]
、nav_menu[*]
或nav_menu_item[*]
的设置 ID。这些设置ID模式分别保留给小工具实例、侧边栏、导航菜单和导航菜单项。如果你需要在你的设置ID中使用 "widget",把它作为后缀而不是前缀,例如 "homepage_widget"
。
设置有两种主要类型:选项(option)和主题修改(theme_mod)。选项直接存储在WordPress数据库的wp_options表中,并应用于网站,而不考虑主题的启用。主题应该尽量少添加选项类型的设置。另一方面,主题修改是特定于某个主题的,大多数主题选项应该是theme_mod。例如,一个自定义的CSS插件可以将一个自定义的主题css设置注册为theme_mod,允许每个主题有一套独特的CSS规则,在切换主题时不会丢失CSS,然后再切换回来。

Theme_mod 和 option 的设置类型例子
通常最重要的是设置的默认值以及它的数据净化回调,这将确保没有不安全的数据被存储在数据库中。典型的主题用法:
$wp_customize->add_setting( 'accent_color', array( 'default' => '#f72525', 'sanitize_callback' => 'sanitize_hex_color', ) );
典型的插件用法:
$wp_customize->add_setting( 'myplugin_options[color]', array( 'type' => 'option', 'capability' => 'manage_options', 'default' => '#ff2525', 'sanitize_callback' => 'sanitize_hex_color', ) );
请注意,定制器可以使用选项类型处理存储为键值数组的设置的选项。这允许多个设置被存储在一个不是theme_mod的选项中。要检索和使用你的定制器选项值,请根据设置ID使用get_theme_mod()
和get_option()
。
function my_custom_css_output() { echo '<style type="text/css" id="custom-theme-css">' . get_theme_mod( 'custom_theme_css', '' ) . '</style>'; echo '<style type="text/css" id="custom-plugin-css">' . get_option( 'custom_plugin_css', '' ) . '</style>'; } add_action( 'wp_head', 'my_custom_css_output');
请注意,get_theme_mod()
和get_option()
的第二个参数是默认值,它应该与你在添加设置时设置的默认值一致。
控件
控件(Controls)是创建用户界面的主要定制器对象。 具体来说,每个控件都必须与一个设置相关联,该设置将把用户输入的数据从控件中保存到数据库中(除了在实时预览中显示它并对其进行净化)。控件可以由定制器管理添加,并以最小的努力提供一套强大的UI选项:
$wp_customize->add_control( 'setting_id', array( 'type' => 'date', 'priority' => 10, // Within the section. 'section' => 'colors', // Required, core or custom. 'label' => __( 'Date' ), 'description' => __( 'This is a date control with a red border.' ), 'input_attrs' => array( 'class' => 'my-custom-class-for-js', 'style' => 'border: 1px solid #900', 'placeholder' => __( 'mm/dd/yyyy' ), ), 'active_callback' => 'is_front_page', ) );
在添加控件时,最重要的参数是它的类型(type),这决定了定制器将显示什么类型的UI。核心提供了几种内置的控件类型:
<input>
任何允许类型的元素(见下文)checkbox
textarea
radio
(用choices
参数传递一个数组,(键)选项值 => (值)标签)select
(用choices
参数传递一个数组,(键)选项值 => (值)标签)dropdown-pages
(用allow_addition
参数,允许用户从控件中添加新的页面)
对于html input元素支持任何input
类型,只需在添加控件时将类型属性值传递给type参数。这样就可以支持text
, hidden
, number
, range
, url
, tel
, email
, search
, time
, date
, datetime
, 和week
等控件类型,但要等待浏览器支持。
控件在显示之前必须被添加到一个板块(板块必须包含要显示的控件)。这可以通过在添加控件时指定section参数来实现。下面是一个添加基本的textarea控件的例子。
$wp_customize->add_control( 'custom_theme_css', array( 'label' => __( 'Custom Theme CSS' ), 'type' => 'textarea', 'section' => 'custom_css', ) );
而这里是一个基本的range(滑块)控件的例子。请注意,大多数浏览器不会显示这个控件的数字值,因为range input类型是为精确值不重要的设置而设计的。如果数字值很重要,请考虑使用number类型。input_attrs
参数将把一个数组:属性 => 值 映射到input元素上的属性,可以用于从占位符文本到自定义脚本中的数据--JavaScript引用的数据等目的。对于number和range控件,它允许我们设置最小、最大和阶梯值。
$wp_customize->add_control( 'setting_id', array( 'type' => 'range', 'section' => 'title_tagline', 'label' => __( 'Range' ), 'description' => __( 'This is the range control description.' ), 'input_attrs' => array( 'min' => 0, 'max' => 10, 'step' => 2, ), ) );
核心自定义控件
如果这些基本的控件类型都不适合您的需要,您可以轻松地创建和添加自定义控件。自定义控件在这篇文章后面会有更全面的解释,但它们本质上是基本WP_Customize_Control
对象的子类,允许任意的html标记和你可能需要的功能。核心有几个内置的自定义控件,允许开发者轻松地实现丰富的JavaScript驱动的功能。可以添加一个颜色选择器控件,如下所示。
$wp_customize->add_control( new WP_Customize_Color_Control( $wp_customize, 'color_control', array( 'label' => __( 'Accent Color', 'theme_textdomain' ), 'section' => 'media', ) ) );
WordPress 4.1和4.2也增加了对任意类型的多媒体内容的支持,有了媒体控件。媒体控件实现了原生的WordPress媒体管理器,允许用户从他们的库中选择文件或上传新文件。通过在添加控件时指定mime_type
参数,你可以指示媒体库显示为特定的类型,如图片或音频。
$wp_customize->add_control( new WP_Customize_Media_Control( $wp_customize, 'image_control', array( 'label' => __( 'Featured Home Page Image', 'theme_textdomain' ), 'section' => 'media', 'mime_type' => 'image', ) ) );
$wp_customize->add_control( new WP_Customize_Media_Control( $wp_customize, 'audio_control', array( 'label' => _( 'Featured Home Page Recording', 'theme_textdomain' ), 'section' => 'media', 'mime_type' => 'audio', ) ) );
请注意,与WP_Customize_Media_Control
相关的设置会保存相关的附件ID,而所有其他与媒体相关的控件(WP_Customize_Upload_Control
的子控件)会将媒体文件的URL保存到设置中。更多信息可以在Make WordPress Core上找到。
此外,WordPress 4.3引入了WP_Customize_Cropped_Image_Control
,它提供了一个在选择图片后裁剪的接口。这对于需要一个特定的长宽比的情况是很有用的。
板块
板块(Sections)是自定义控件的UI容器。虽然你可以在核心板块添加自定义控件,但如果你有超过几个选项,你可能想添加一个或多个自定义板块。使用WP_Customize_Manager对象的add_section
方法来添加一个新的板块。
$wp_customize->add_section( 'custom_css', array( 'title' => __( 'Custom CSS' ), 'description' => __( 'Add custom CSS here' ), 'panel' => '', // Not typically needed. 'priority' => 160, 'capability' => 'edit_theme_options', 'theme_supports' => '', // Rarely needed. ) );
你只需要包含那些你想覆盖默认值的字段,例如,默认的优先级(排序)通常是可以接受的。如果你的选项一目了然,那么大多数板块不需要“描述”文本。如果你确实想改变自定义板块的位置,核心板块的优先级见下表:
Title | ID | Priority (Order) |
Site Title & Tagline | title_tagline | 20 |
Colors | colors | 40 |
Header Image | header_image | 60 |
Background Image | background_image | 80 |
Menus (Panel) | nav_menus | 100 |
Widgets (Panel) | widgets | 110 |
Static Front Page | static_front_page | 120 |
default | 160 | |
Additional CSS | custom_css | 200 |
在大多数情况下,只需指定一个或两个参数就可以添加板块。下面是一个添加与主题页脚有关的选项板块的例子:
// Add a footer/copyright information section. $wp_customize->add_section( 'footer' , array( 'title' => __( 'Footer', 'themename' ), 'priority' => 105, // Before Widgets. ) );
面板
定制器面板(Panels)API是在WordPress 4.0中引入的,它允许开发者在控件和板块之外创建一个额外的层次结构。面板不仅仅是简单地将控件分组,它被设计用来为定制器提供不同的上下文,比如自定义小工具、菜单,或者也许在未来,编辑文章。板块和面板对象之间有一个重要的技术区别。
在大多数情况下,主题不应该注册自己的面板。板块不需要嵌套在面板下,而且每个板块一般都应该包含多个控件。控件也应该被添加到核心提供的版块中,比如在颜色版块中添加颜色选项。还要确保你的选项尽可能地精简和有效,请看WordPress的哲学。面板被设计为整个功能的上下文,如Widgets、Menus或Posts,而不是作为通用版块的包装。如果你一定要使用面板,你会发现它的API和版块的API几乎是一样的。
$wp_customize->add_panel( 'menus', array( 'title' => __( 'Menus' ), 'description' => $description, // Include html tags such as <p>. 'priority' => 160, // Mixed with top-level-section hierarchy. ) ); $wp_customize->add_section( $section_id , array( 'title' => $menu->name, 'panel' => 'menus', ) );
面板必须至少包含一个板块,该板块必须至少包含一个控件,才能显示。正如你在上面的例子中所看到的,板块可以被添加到面板中,这与控件被添加到板块中的方式相似。然而,与控件不同的是,如果在注册板块时面板参数为空,它将显示在主要的、顶级的定制器上下文中,因为大多数板块不应该包含在面板中。
自定义控件、板块和面板
通过子类化与每个定制器对象相关的PHP对象,可以很容易地创建自定义控件、板块和面板:WP_Customize_Control
, WP_Customize_Section
, 和WP_Customize_Panel
(这也可以用于WP_Customize_Setting
,但自定义设置通常最好使用自定义设置类型来实现,这在下一节有介绍)。下面是一个基本自定义控件的例子。
class WP_New_Menu_Customize_Control extends WP_Customize_Control { public $type = 'new_menu'; /** * Render the control's content. */ public function render_content() { ?> <button class="button button-primary" id="create-new-menu-submit" tabindex="0"><?php _e( 'Create Menu' ); ?></button> <?php } }
通过对基础控制类的子类化,你可以用自定义功能覆盖任何功能,或者根据你的需要使用核心功能。最常见的覆盖功能是render_content()
,因为它允许你用HTML从头开始创建自定义UI。然而,自定义控件应该谨慎使用,因为它们可能会引入与周围的核心用户界面不一致的用户界面,并给用户带来混乱。定制器对象的添加方式与默认控件、板块和面板的添加方式类似。
$wp_customize->add_control( new WP_Customize_Color_Control( $wp_customize, // WP_Customize_Manager 'accent_color', // Setting id array( // Args, including any custom ones. 'label' => __( 'Accent Color' ), 'section' => 'colors', ) ) );
添加控件时传递的参数被映射到控件类中的类变量,所以你可以添加和使用自定义的,在不同的实例中你的自定义对象的某些部分是不同的。
在创建自定义控件、板块或面板时,强烈建议参考核心代码,以便充分了解可以被覆盖的可用功能。核心还包括每种类型的自定义对象的例子。这可以在wp-includes/class-wp-customize-control.php、wp-includes/class-wp-customize-section.php和wp-includes/class-wp-customize-panel.php中找到。每个定制器对象类型也有一个JavaScript API,它可以用自定义对象来扩展;更多细节请看定制器 JavaScript API部分。
定制器UI标准
自定义控件、板块和面板应该尽可能地与核心的用户界面做法相匹配。这包括依靠wp-admin的标准,例如使用.button
和.button-primary
类。也有一些专门针对定制器的标准(从WordPress 4.7开始)。
- 白色背景颜色仅用于指示导航和可操作项目(如inputs)
- 一般的
#eee
背景色提供了与白色元素的视觉对比 1px #ddd
边框将导航元素与背景边距彼此分开- 在需要视觉分离的元素之间提供
15px
的间距 4px
边框用于导航元素一侧以显示悬停或焦点,颜色为#0073aa
- 定制器文本使用颜色
#555d66
,导航元素的悬停和焦点状态使用#0073aa
自定义设置类型
默认情况下,定制器支持将设置保存为选项或主题修改。但是这种行为可以很容易地被覆盖,以便在WordPress数据库的wp_options表之外手动保存和预览设置,或者应用其他自定义处理。要开始的话,在添加你的设置时指定一个选项或主题修改以外的类型(你可以使用几乎任何字符串)。
$wp_customize->add_setting( $nav_menu_setting_id, array( 'type' => 'nav_menu', 'default' => $item_ids, ) );
当设置的值在相关的控件中被改变时,该设置将不再被保存或预览。现在,你可以使用customize_update_$setting->type
和 customize_preview_$setting->type
动作来实现自定义保存和预览功能。下面是一个从Menu Customizer项目中保存一个菜单项的顺序属性的例子(设置的值是一个有序的菜单ID数组)。
function menu_customizer_update_nav_menu( $value, $setting ) { $menu_id = str_replace( 'nav_menu_', '', $setting->id ); // ... $i = 0; foreach( $value as $item_id ) { // $value is ordered array of item ids. menu_customizer_update_menu_item_order( $menu_id, $item_id, $i ); $i++; } } add_action( 'customize_update_nav_menu', 'menu_customizer_update_nav_menu', 10, 2 );
而这里是同一个插件如何实现对导航菜单项的预览(注意这个例子需要PHP5.3或更高版本)
function menu_customizer_preview_nav_menu( $setting ) { $menu_id = str_replace( 'nav_menu_', '', $setting->id ); add_filter( 'wp_get_nav_menu_items', function( $items, $menu, $args ) use ( $menu_id, $setting ) { $preview_menu_id = $menu->term_id; if ( $menu_id == $preview_menu_id ) { $new_ids = $setting->post_value(); foreach ( $new_ids as $item_id ) { $item = wp_setup_nav_menu_item( $item ); $item->menu_order = $i; $new_items[] = $item; $i++; } return $new_items; } else { return $items; } }, 10, 3 ); } add_action( 'customize_preview_nav_menu', 'menu_customizer_preview_nav_menu', 10, 2 );