배열이 포함 된 설정 API 예제


32

Wrox WordPress 플러그인 개발 책을 새 플러그인을 시작하기위한 기본 참조로 사용하고 있으며 모든 설정을 1 배열로 저장할 수 있지만이 책의 예는 제공하지 않습니다. 웹에서 찾은 결과는 예제마다 다릅니다. Konstantin게시물의 후반부 는 나를 가깝게하지만 여러 필드가있는 더 완벽한 예를보고 싶습니다.

답변:


32

짧은 대답 : 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.phpoptions.php

좋아, 미친 것처럼 등록하자 :

  1. 우리는 페이지의 옵션 값을 가져 와서 일부 기본값과 구문 분석합니다. 꽤 기본입니다.

  2. 이름으로 설정 그룹을 등록합니다 plugin:t5_sae_option_group. 나는 접두사가 붙은 이름을 좋아하는데, 정렬하고 이해하는 것이 더 쉽습니다.

  3. 그런 다음 1과 2의 두 섹션을 등록합니다.

  4. 그리고 첫 번째 섹션에는 두 개, 두 번째 섹션에는 세 개의 섹션을 추가합니다. 옵션 이름과 이스케이프 된 값을 각 필드의 콜백 함수에 전달합니다. 출력 핸들러는 데이터를 변경해서는 안되며 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가 작동하지 않기 때문에 네트워크 플러그인을 작성할 때 그렇게해야합니다.

여기에 언급하지 않은 일부 엣지 케이스와 불완전한 부품도 있습니다. 필요할 때 찾을 수 있습니다. :)


와우 고마워. 이것은 매우 도움이됩니다. 내가 읽은 다른 게시물 중 어느 것도 네트워크 플러그인에 대해 언급하지 않았습니다.
Bjorn

이것에 대한 부록입니다. 확인란을 표시 / 저장하려는 경우 콜백 코드를 '<input type = "checkbox"id = "% 3 $ s"name = "% 1 $ s [% 2 $ s] value ="로 변경했습니다. % 4 $ s " '. checked ('on ', $ args ['value '], false).'/> '
joesk

답변 검토 단일 콜론을 포함하는 plugin : t5_sae_option_group 을 사용하여 당황합니다 . 나는 철저하게 보았고이 구문에 대한 설명을 찾지 못했습니다. PHP 문서에서 이에 대한 설명을 말씀해 주시겠습니까? 감사합니다

@ user50909 : 저에게 간단한 문자열 식별자처럼 보입니다. PHP 구문은 중요하지 않습니다.
s_ha_dum

1
@ 댄 시도 basename( $_SERVER['REQUEST_URI'] ).
fuxia
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.