#1 楼
简短的答案:您的name
属性值必须使用架构option_name[array_key]
。因此,当您使用... <input name="option_name[key1]">
<input name="option_name[key2]">
...时,您会在验证函数中得到一个数组作为选项值:
array (
'key1' => 'some value',
'key2' => 'some other value'
)
PHP为您做到了,这不是WordPress功能。 :)
如何使它与设置API一起使用?
比方说,我们需要此选项页面,所有值都应存储在一个选项中,并在一个选项中进行验证函数。
选项页面
我们需要钩子
admin_menu
和两个功能:一个要注册页面,一个呈现输出。add_action( 'admin_menu', 't5_sae_add_options_page' );
function t5_sae_add_options_page()
{
add_options_page(
'T5 Settings API Example', // $page_title,
'T5 SAE', // $menu_title,
'manage_options', // $capability,
't5_sae_slug', // $menu_slug
't5_sae_render_page' // Callback
);
}
function t5_sae_render_page()
{
?>
<div class="wrap">
<h2><?php print $GLOBALS['title']; ?></h2>
<form action="options.php" method="POST">
<?php
settings_fields( 'plugin:t5_sae_option_group' );
do_settings_sections( 't5_sae_slug' );
submit_button();
?>
</form>
</div>
<?php
}
形式
action
必须为options.php
,否则将不调用验证。查看wp-admin/options-permalink.php
的PHP源代码-有一个隐藏的陷阱do_settings_sections('permalink');
-但它不能工作,因为形式action
是错误的。现在,返回到我们的自定义页面。我们使它比WordPress更好。
注册设置,部分和字段
我们在需要时挂入
admin_init
并调用注册函数。if ( ! empty ( $GLOBALS['pagenow'] )
and ( 'options-general.php' === $GLOBALS['pagenow']
or 'options.php' === $GLOBALS['pagenow']
)
)
{
add_action( 'admin_init', 't5_sae_register_settings' );
}
这里的重要部分是:
$GLOBALS['pagenow']
必须是options-general.php
(用于输出)或options.php
(用于验证)。不要在每个请求上调用以下所有代码。多数教程和几乎所有插件都犯了这个错误。好吧,让我们疯狂注册:
我们获取页面的选项值,并针对某些选项进行解析默认值。很简单。
我们注册一个名称为
plugin:t5_sae_option_group
的设置组。我喜欢带前缀的名称,它们更易于排序和理解。然后我们注册两个部分,分别为1和2。
我们添加了三个部分,两个用于第一部分,一个用于第二部分。 。我们将选项名称和转义值传递给每个字段的回调函数。输出处理程序不应更改数据,只需添加一些HTML。
function t5_sae_register_settings()
{
$option_name = 'plugin:t5_sae_option_name';
// Fetch existing options.
$option_values = get_option( $option_name );
$default_values = array (
'number' => 500,
'color' => 'blue',
'long' => ''
);
// Parse option values into predefined keys, throw the rest away.
$data = shortcode_atts( $default_values, $option_values );
register_setting(
'plugin:t5_sae_option_group', // group, used for settings_fields()
$option_name, // option name, used as key in database
't5_sae_validate_option' // validation callback
);
/* No argument has any relation to the prvious register_setting(). */
add_settings_section(
'section_1', // ID
'Some text fields', // Title
't5_sae_render_section_1', // print output
't5_sae_slug' // menu slug, see t5_sae_add_options_page()
);
add_settings_field(
'section_1_field_1',
'A Number',
't5_sae_render_section_1_field_1',
't5_sae_slug', // menu slug, see t5_sae_add_options_page()
'section_1',
array (
'label_for' => 'label1', // makes the field name clickable,
'name' => 'number', // value for 'name' attribute
'value' => esc_attr( $data['number'] ),
'option_name' => $option_name
)
);
add_settings_field(
'section_1_field_2',
'Select',
't5_sae_render_section_1_field_2',
't5_sae_slug', // menu slug, see t5_sae_add_options_page()
'section_1',
array (
'label_for' => 'label2', // makes the field name clickable,
'name' => 'color', // value for 'name' attribute
'value' => esc_attr( $data['color'] ),
'options' => array (
'blue' => 'Blue',
'red' => 'Red',
'black' => 'Black'
),
'option_name' => $option_name
)
);
add_settings_section(
'section_2', // ID
'Textarea', // Title
't5_sae_render_section_2', // print output
't5_sae_slug' // menu slug, see t5_sae_add_options_page()
);
add_settings_field(
'section_2_field_1',
'Notes',
't5_sae_render_section_2_field_1',
't5_sae_slug', // menu slug, see t5_sae_add_options_page()
'section_2',
array (
'label_for' => 'label3', // makes the field name clickable,
'name' => 'long', // value for 'name' attribute
'value' => esc_textarea( $data['long'] ),
'option_name' => $option_name
)
);
}
当我们在页面中调用
do_settings_sections( 't5_sae_slug' );
时,将自动调用这些节和字段的所有回调处理程序。我们已经做到了,所以我们只需要... 打印字段
请注意
name
属性是如何构建的:传递的option_name
是第一部分,数组键如下在方括号[]
中。function t5_sae_render_section_1()
{
print '<p>Pick a number between 1 and 1000, and choose a color.</p>';
}
function t5_sae_render_section_1_field_1( $args )
{
/* Creates this markup:
/* <input name="plugin:t5_sae_option_name[number]"
*/
printf(
'<input name="%1$s[%2$s]" id="%3$s" value="%4$s" class="regular-text">',
$args['option_name'],
$args['name'],
$args['label_for'],
$args['value']
);
// t5_sae_debug_var( func_get_args(), __FUNCTION__ );
}
function t5_sae_render_section_1_field_2( $args )
{
printf(
'<select name="%1$s[%2$s]" id="%3$s">',
$args['option_name'],
$args['name'],
$args['label_for']
);
foreach ( $args['options'] as $val => $title )
printf(
'<option value="%1$s" %2$s>%3$s</option>',
$val,
selected( $val, $args['value'], FALSE ),
$title
);
print '</select>';
// t5_sae_debug_var( func_get_args(), __FUNCTION__ );
}
function t5_sae_render_section_2()
{
print '<p>Makes some notes.</p>';
}
function t5_sae_render_section_2_field_1( $args )
{
printf(
'<textarea name="%1$s[%2$s]" id="%3$s" rows="10" cols="30" class="code">%4$s</textarea>',
$args['option_name'],
$args['name'],
$args['label_for'],
$args['value']
);
}
哦,我介绍了一个函数
t5_sae_debug_var()
。它是:function t5_sae_debug_var( $var, $before = '' )
{
$export = esc_html( var_export( $var, TRUE ) );
print "<pre>$before = $export</pre>";
}
很有用,看看我们是否达到了预期。
现在,这很好用,我们只需要一个事情:
验证选项数组
因为我们使用了括号符号,所以我们的值是一个数组。我们只需要遍历每个元素并进行验证即可。
function t5_sae_validate_option( $values )
{
$default_values = array (
'number' => 500,
'color' => 'blue',
'long' => ''
);
if ( ! is_array( $values ) ) // some bogus data
return $default_values;
$out = array ();
foreach ( $default_values as $key => $value )
{
if ( empty ( $values[ $key ] ) )
{
$out[ $key ] = $value;
}
else
{
if ( 'number' === $key )
{
if ( 0 > $values[ $key ] )
add_settings_error(
'plugin:t5_sae_option_group',
'number-too-low',
'Number must be between 1 and 1000.'
);
elseif ( 1000 < $values[ $key ] )
add_settings_error(
'plugin:t5_sae_option_group',
'number-too-high',
'Number must be between 1 and 1000.'
);
else
$out[ $key ] = $values[ $key ];
}
elseif ( 'long' === $key )
{
$out[ $key ] = trim( $values[ $key ] );
}
else
{
$out[ $key ] = $values[ $key ];
}
}
}
return $out;
}
这很丑陋。我不会在生产中使用此类代码。但是它做了它应该做的事情:它返回一个经过验证的值数组。当我们调用
get_option()
时,WordPress将序列化数组,将其以我们的选项名称存储在数据库中,并以未序列化的方式返回它。所有这些都可以,但是不必要的复杂,我们得到1998年的标记(
<tr valign="top">
)和许多冗余。必要时使用设置API。另外,也可以使用
admin_url( 'admin-post.php' )
作为表单操作(请查看其源代码),并使用自己的代码(可能更精美的代码)创建完整的设置页面。实际上,编写网络插件时必须这样做,因为设置API在那里不起作用。
还有一些边缘情况和不完整的零件,我在这里没有提到–您将在需要时找到它们。 :)
评论
哇谢谢。这非常有帮助。我读过的其他任何一篇文章都没有提到有关网络插件的任何内容,这是我将来会记住的重要注意事项。
–比约恩
13年5月21日在5:37
只是对此的附录。如果您尝试显示/存储复选框,则我已将回调代码更改为:''
–joesk
2014年4月10日在16:25
复习答案我对使用plugin:t5_sae_option_group包含一个冒号感到困惑。我已经详尽地查找过,但没有找到对此语法的解释。您能否在PHP文档中指出对此的解释?谢谢
–user50909
2014年4月27日14:41
@ user50909:对我来说,这些看起来像简单的字符串标识符。 PHP语法不应成为一个因素。
– s_ha_dum
2014年4月27日在15:04
@Dan尝试使用基名($ _SERVER ['REQUEST_URI'])。
– fuxia♦
2014年5月26日13:48