Câu trả lời ngắn: name
giá trị thuộc tính của bạn phải sử dụng lược đồ option_name[array_key]
. Vì vậy, khi bạn sử dụng thì
<input name="option_name[key1]">
<input name="option_name[key2]">
Bạn có thể nhận được một mảng làm giá trị tùy chọn trong chức năng xác nhận của mình:
array (
'key1' => 'some value',
'key2' => 'some other value'
)
PHP làm điều đó cho bạn, đây không phải là một tính năng của WordPress. :)
Làm cách nào để làm việc với API cài đặt?
Giả sử, chúng tôi muốn trang tùy chọn này và tất cả các giá trị sẽ được lưu trữ trong một tùy chọn và được xác thực trong một chức năng.
Trang tùy chọn
Chúng ta cần hook admin_menu
và hai chức năng: một để đăng ký trang, một để hiển thị đầu ra.
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
}
Các hình thức action
phải được options.php
, hoặc xác nhận sẽ không được gọi. Nhìn vào nguồn PHP của wp-admin/options-permalink.php
- có một cái bẫy ẩn do_settings_sections('permalink');
- nhưng nó không thể hoạt động được vì hình thức action
bị sai.
Bây giờ, trở lại trang tùy chỉnh của chúng tôi. Chúng tôi làm cho nó tốt hơn WordPress.
Đăng ký cài đặt, phần và trường
Chúng tôi kết nối admin_init
khi cần và gọi chức năng đăng ký.
if ( ! empty ( $GLOBALS['pagenow'] )
and ( 'options-general.php' === $GLOBALS['pagenow']
or 'options.php' === $GLOBALS['pagenow']
)
)
{
add_action( 'admin_init', 't5_sae_register_settings' );
}
Phần quan trọng ở đây là: $GLOBALS['pagenow']
phải là options-general.php
(cho đầu ra) hoặc options.php
(cho xác nhận). Không gọi tất cả các mã sau đây trên mỗi yêu cầu. Hầu hết các hướng dẫn và hầu hết tất cả các plugin đều sai.
Được rồi, hãy đăng ký như điên:
Chúng tôi tìm nạp các giá trị tùy chọn cho trang của mình và phân tích chúng theo một số giá trị mặc định. Khá cơ bản.
Chúng tôi đăng ký một nhóm cài đặt với tên plugin:t5_sae_option_group
. Tôi thích tên tiền tố, chúng dễ sắp xếp và hiểu theo cách này.
Sau đó, chúng tôi đăng ký hai phần, 1 và 2.
Và chúng tôi thêm ba phần, hai cho phần đầu tiên, một cho phần thứ hai. Chúng tôi chuyển tên tùy chọn và giá trị thoát cho các hàm gọi lại cho từng trường. Trình xử lý đầu ra không nên thay đổi dữ liệu, chỉ cần thêm một số 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
)
);
}
Tất cả các trình xử lý gọi lại cho các phần và trường sẽ được gọi tự động khi chúng tôi gọi do_settings_sections( 't5_sae_slug' );
trong trang của chúng tôi. Chúng tôi đã làm điều đó rồi, vì vậy chúng tôi chỉ cần đến
In các trường
Lưu ý cách các name
thuộc tính được xây dựng: thông qua option_name
là phần đầu tiên, khóa mảng theo dấu ngoặc vuông []
.
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']
);
}
Ồ, tôi đã giới thiệu một chức năng t5_sae_debug_var()
. Đây là:
function t5_sae_debug_var( $var, $before = '' )
{
$export = esc_html( var_export( $var, TRUE ) );
print "<pre>$before = $export</pre>";
}
Hữu ích để xem nếu chúng ta có những gì chúng ta mong đợi.
Bây giờ, điều này hoạt động khá tốt, chúng ta chỉ cần một điều:
Xác thực mảng tùy chọn
Bởi vì chúng tôi đã sử dụng ký hiệu ngoặc, giá trị của chúng tôi là một mảng. Chúng ta chỉ cần đi qua từng yếu tố và xác nhận nó.
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;
}
Điều này khá xấu xí; Tôi sẽ không sử dụng mã như vậy trong sản xuất. Nhưng nó làm những gì nó cần: nó trả về một mảng các giá trị được xác nhận. WordPress sẽ tuần tự hóa mảng, lưu trữ nó dưới tên tùy chọn của chúng tôi trong cơ sở dữ liệu và trả lại nó không được xác thực khi chúng ta gọi get_option()
.
Tất cả điều này hoạt động, nhưng nó phức tạp không cần thiết, chúng tôi nhận được đánh dấu từ năm 1998 ( <tr valign="top">
) và nhiều dự phòng.
Sử dụng API cài đặt khi bạn phải. Là một cách sử dụng khác admin_url( 'admin-post.php' )
như hành động biểu mẫu (nhìn vào nguồn của nó) và tạo trang cài đặt hoàn chỉnh với mã riêng, có thể thanh lịch hơn của bạn.
Thực tế, bạn phải làm điều đó khi bạn viết một plugin mạng, vì API cài đặt không hoạt động ở đó.
Ngoài ra còn có một số trường hợp cạnh và các phần không hoàn chỉnh mà tôi đã không đề cập ở đây - bạn sẽ tìm thấy chúng khi bạn cần chúng. :)