API cài đặt với ví dụ mảng


32

Tôi đang sử dụng cuốn sách phát triển plugin WordPress của WordPress làm tài liệu tham khảo chính để bắt đầu với một plugin mới và tôi hiểu tất cả các cài đặt có thể được lưu dưới dạng 1 mảng nhưng cuốn sách không đưa ra ví dụ về điều này và tất cả những thứ tôi tìm kiếm trên web có vẻ rất khác nhau từ ví dụ này sang ví dụ khác. Nửa sau của một bài đăng của Konstantin khiến tôi gần gũi nhưng tôi thực sự muốn xem một ví dụ đầy đủ hơn với nhiều lĩnh vực.

Câu trả lời:


32

Câu trả lời ngắn: namegiá 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.

nhập mô tả hình ảnh ở đây

Trang tùy chọn

Chúng ta cần hook admin_menuvà 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 actionphả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 actionbị 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:

  1. 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.

  2. 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.

  3. Sau đó, chúng tôi đăng ký hai phần, 1 và 2.

  4. 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 namethuộc tính được xây dựng: thông qua option_namelà 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. :)


Ồ cảm ơn nhé. Điều này rất hữu ích. Không có bài viết nào tôi đọc được đề cập bất cứ điều gì về plugin mạng, đây là một lưu ý quan trọng mà tôi sẽ ghi nhớ trong tương lai.
Bjorn

Chỉ là một phụ lục cho điều này. Nếu bạn đang cố gắng hiển thị / lưu trữ các hộp kiểm, tôi đã thay đổi mã gọi lại thành: '<input type = "hộp kiểm" id = "% 3 $ s" name = "% 1 $ s [% 2 $ s] value =" % 4 $ s "'. Đã kiểm tra (' trên ', $ args [' value '], sai).' /> '
joesk

Xem lại câu trả lời Tôi bối rối khi sử dụng plugin: t5_sae_option_group bao gồm một dấu hai chấm. Tôi đã xem xét kỹ lưỡng và không tìm thấy một lời giải thích về cú pháp này. Bạn có thể chỉ ra một lời giải thích về điều này trong tài liệu PHP không? Cảm ơn

@ user50909: những cái đó trông giống như định danh chuỗi đơn giản với tôi. Cú pháp PHP không nên là một yếu tố.
s_ha_dum

1
@Dan Hãy thử basename( $_SERVER['REQUEST_URI'] ).
fuxia
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.