คำตอบสั้น ๆ : คุณค่าแอตทริบิวต์ต้องใช้คี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
ฟังก์ชั่นhook และสองฟังก์ชั่นหนึ่งอันเพื่อลงทะเบียนหน้าหนึ่งฟังก์ชั่นเพื่อแสดงผล
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
มิฉะนั้นจะไม่สามารถตรวจสอบความถูกต้องได้ ดูที่แหล่ง PHP ของwp-admin/options-permalink.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
และเราเพิ่มสามส่วนสองส่วนสำหรับส่วนแรกหนึ่งส่วนสำหรับสอง เราส่งชื่อตัวเลือกและค่าEscapeไปยังฟังก์ชันการโทรกลับสำหรับแต่ละฟิลด์ เครื่องมือจัดการผลลัพธ์ไม่ควรเปลี่ยนแปลงข้อมูลเพียงเพิ่ม 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;
}
มันค่อนข้างน่าเกลียด ฉันจะไม่ใช้รหัสดังกล่าวในการผลิต แต่มันทำในสิ่งที่มันควรจะ: มันจะส่งกลับอาร์เรย์ของค่า WordPress จะเรียงลำดับอาเรย์เป็นลำดับเก็บไว้ภายใต้ชื่อตัวเลือกของเราในฐานข้อมูลและส่งคืนค่าแบบไม่ระบุเวลาเมื่อเราเรียกget_option()
ใช้
งานทั้งหมดนี้ แต่มันไม่ซับซ้อนที่ไม่จำเป็นเราได้รับมาร์กอัปจากปี 1998 ( <tr valign="top">
) และความซ้ำซ้อนมากมาย
ใช้ API การตั้งค่าเมื่อคุณต้องการ เพื่อใช้เป็นทางเลือกadmin_url( 'admin-post.php' )
ในการดำเนินการกับแบบฟอร์ม (ดูแหล่งที่มาของมัน) และสร้างหน้าการตั้งค่าที่สมบูรณ์ด้วยโค้ดของคุณเองซึ่งอาจจะดูหรูหรากว่า
ที่จริงแล้วคุณต้องทำอย่างนั้นเมื่อคุณเขียนปลั๊กอินเครือข่ายเนื่องจาก API การตั้งค่าไม่ทำงาน
นอกจากนี้ยังมีเคสขอบและชิ้นส่วนที่ไม่สมบูรณ์ที่ฉันไม่ได้พูดถึงที่นี่คุณจะพบพวกเขาเมื่อคุณต้องการ :)