Как передать переменную в обратный вызов add_settings_section ()?

16

Я пытаюсь максимально автоматизировать вызовы функций API настроек для каждого параметра в плагине. Цикл по массиву опций и вывод add_settings_section()и add_settings_field()достаточно прост:

add_settings_section():

$oenology_hooks_tabs = oenology_hooks_get_settings_page_tabs();
foreach ( $oenology_hooks_tabs as $tab ) {
    $tabname = $tab['name'];
    $tabtitle = $tab['title'];
    $tabsections = $tab['sections'];
    foreach ( $tabsections as $section ) {
        $sectionname = $section['name'];
        $sectiontitle = $section['title'];
        $sectiondescription = $section['description'];
        // Add settings section
        add_settings_section(
            'oenology_hooks_' . $sectionname . '_section',
            $sectiontitle,
            'oenology_hooks_' . $sectionname . '_text',
            'oenology_hooks_' . $tabname . '_tab'
        );
    }
}

И `add_settings_field ():

global $oenology_hooks;
$oenology_hooks = oenology_hooks_get_hooks();

foreach ( $oenology_hooks as $hook ) {
    $hookname = $hook['name'];
    $hooktitle = $hook['title'];
    $hooktab = $hook['tab'];
    $hooksection = $hook['section'];
    add_settings_field(
        'oenology_hooks_' . $hookname,
        $hooktitle,
        'oenology_hooks_setting_callback',
        'oenology_hooks_' . $hooktab . '_tab',
        'oenology_hooks_' . $hooksection . '_section',
        $hook
    );
}

С помощью add_settings_field()я могу легко написать общий обратный вызов, передав $hookпеременную обратному вызову в качестве пятого параметра в вызове функции:

function oenology_hooks_setting_callback( $hook ) {
    $oenology_hooks_options = get_option( 'plugin_oenology_hooks_settings' ); 
    $hookname = $hook['name'];
    $hooktitle = $hook['title'];
    $hookdescription = $hook['description'];
    $hooktype = $hook['type'];
    $hooktab = $hook['tab'];
    $hooksection = $hook['section'];
    $inputvalue = $hookname . '_hide';
    $inputname = 'plugin_oenology_hooks_settings[' . $inputvalue . ']';
    $textareaname = 'plugin_oenology_hooks_settings[' . $hookname . ']';
    $textareavalue = $oenology_hooks_options[$hookname];
    if ( 'Filter' == $hooktype ) {
        ?>
        <input type="checkbox" name="<?php echo $inputname; ?>" value="<?php echo $inputvalue;?>" <?php checked( true == $oenology_hooks_options[$inputvalue]  ); ?> />
        <span>Hide <?php echo $hooktitle; ?> content?</span><br />
        <?php
    }
    ?>
    <span class="description"><?php echo $hooktype; ?> Hook: <?php echo $hookdescription; ?></span><br />
    <textarea name="<?php echo $textareaname; ?>" cols="80" rows="3" ><?php 
        echo esc_textarea( $textareavalue ); 
    ?></textarea>
    <?php 
}

Однако, похоже, что add_settings_section()не имеет аналогичного $argsпараметра; таким образом, я не могу использовать тот же метод для передачи $sectionпеременной в обратный вызов.

Таким образом, мой вопрос: есть ли способ передать переменную в add_settings_section()обратный вызов или какой-то другой способ создать обратный вызов, аналогичный тому, для которого я делаю add_settings_field()?

РЕДАКТИРОВАТЬ:

@Bainternet прибил это! Вот мой рабочий код:

/**
 * Callback for add_settings_section()
 * 
 * Generic callback to output the section text
 * for each Plugin settings section. 
 * 
 * @param   array   $section_passed Array passed from add_settings_section()
 */
function oenology_hooks_sections_callback( $section_passed ) {
    global $oenology_hooks_tabs;
    $oenology_hooks_tabs = oenology_hooks_get_settings_page_tabs();
    foreach ( $oenology_hooks_tabs as $tab ) {
        $tabname = $tab['name'];
        $tabsections = $tab['sections'];
        foreach ( $tabsections as $section ) {
            $sectionname = $section['name'];
            $sectiondescription = $section['description'];
            $section_callback_id = 'oenology_hooks_' . $sectionname . '_section';
            if ( $section_callback_id == $section_passed['id'] ) {
                ?>
                <p><?php echo $sectiondescription; ?></p>
                <?php
            }
        }
    }
}
Чип Беннетт
источник
1
Просто знаком: Почему вы не extract( $args, EXTR_SKIP );в начале oenology_hooks_setting_callback(), так что вам не нужно сохранять каждую часть массива в новую $var? Они будут доступны $'name_inside_the_array, например, с. '$ title , $ tab` и т. д.
kaiser
... потому что я не настолько умён с PHP? :) Я попробую; Благодарность!
Чип Беннетт
Может быть, вы захотите взглянуть на этот Gist , который показывает пример «возможно, лучшей практики» о том, как добавлять фильтры и хуки, анализировать аргументы и обрабатывать ввод строки запроса. Он немного староват, и я, скорее всего, переделаю его, когда у меня будет время, но, на мой взгляд, стоит посмотреть :)
Кайзер
На самом деле это просто плагин, который добавляет интерфейс для хуков, которые я добавил в Oenology. Я довольно доволен тем, как я на самом деле добавил хуки в тему. Сейчас я просто пытаюсь предоставить удобный способ показать их конечным пользователям.
Чип Беннетт
Я не поняла тебя. Я просто хотел показать вам это на случай, если это поможет вам (когда угодно). Я считаю этот код чем-то ироничным - просто посмотрите, сколько усилий нужно приложить всем и каждому для всех в стиле wordpress ...
kaiser

Ответы:

18

если вы посмотрите на функцию do_settings_sections более конкретно на строку 1164, где выполняется функция обратного вызова:

call_user_func($section['callback'], $section);

вы можете видеть, что массив $ section передается в функцию обратного вызова, поэтому вы можете определить обратный вызов по $section['id']

надеюсь, что это сделать с тех пор.

Обновить

Вот пример, если ваш обратный вызов add_settings_section для всех разделов был назван, oenology_hooks_section_callbackвы можете определить его следующим образом:

function oenology_hooks_section_callback($section_passed){
    if ($section_passed['id'] == 'whatever_section_id'){
        //do stuff
    }
    if ($section_passed['id'] == 'whatever_section_id_number2'){
        //do other stuff
    }
 }

и делать вещи, я имею в виду делать все, что вы хотите сделать с этим обратным вызовом раздела.

Bainternet
источник
Хм ... это выглядит многообещающе. Как мне определить $section['id']?
Чип Беннетт
@Chip Bennett idбудет первым аргументом, который вы передадитеadd_settings_section()
Rarst
@Chip Bennett Я добавил пример, чтобы попытаться объяснить лучше.
Bainternet
@Bainternet: Потрясающе! У меня есть дополнительный сценарий, и я столкнулся с той же проблемой, что и Чип Беннет. Теперь это работает как шарм. Благодарю.
Ань Чан
Ладно, вот и все, наконец, за выходные; Позвольте мне попробовать код, который я имею в виду, и я сообщу.
Чип Беннетт
4

Я знаю, что это старый вопрос, но я добавлю свои два цента, на случай, если кто-то еще придет; более простой способ сделать это - написать собственную модификацию add_settings_section()функции, которая добавит только параметр args обратного вызова в его конец.

Это будет выглядеть так (или что-то вроде этого)

function my_add_settings_section($id, $title, $callback, $page, $callbackargs) {

global $wp_settings_sections;

if ( !isset($wp_settings_sections) ) 
{
    $wp_settings_sections = array();
}

if ( !isset($wp_settings_sections[$page]) )
{
    $wp_settings_sections[$page] = array();
}

if ( !isset($wp_settings_sections[$page][$id]) )
{
    $wp_settings_sections[$page][$id] = array();
}

$wp_settings_sections[$page][$id] = array( 'id' => $id, 'title' => $title, 'callback' => $callback, 'callbackargs' => $callbackargs, 'page' => 'page' );
}

Теперь вы просто использовали бы это вместо встроенной функции wordpress и получили бы доступ к своим аргументам обратного вызова через 'callbackargs'клавишу массива обычным способом, как это

function oenology_hooks_sections_callback( $section_passed ) {
   // Our callback arguments  
   $section_passed['callbackargs']
}

Который мы могли бы использовать, чтобы перейти к какой-то другой функции:

 function oenology_hooks_sections_callback( $section_passed ) {
   // Our callback arguments  
   $args = $section_passed['callbackargs'];
   some_other_function( $args );
}

Или аргументы обратного вызова могут быть самим массивом, который мы используем:

function oenology_hooks_sections_callback( $section_passed ) {
   // Our callback arguments  
   if ( $section_passed['callbackargs']['stuff'] !== 'things' ) 
   {
       echo 'stuff is not things!";
   }
}

Это все возможно, потому что все, что add_settings_section()нужно, это добавить новый элемент массива в $wp_settings_sectionsглобальную переменную, этот новый элемент массива может быть самим массивом, содержащим любое количество ключей с разными именами, которые могут быть использованы любой функцией, которая знала, что они там находятся. Когда do_settings_sectionsназывают call_user_func_arrayэто проходит В $sectionsпараметр , как указан Bainternet, это означает , что весь массив мы добавили $wp_settings_sectionsв my_add_settings_section()просеивают в наш обратный вызов, то есть у нас есть доступ к каждому новому члену массива мы добавим к нему , таким как callbackargsпозволяя нашу функция , чтобы иметь полный окрыленный обратный звонок.

Несмотря на то, что я уверен, что это может быть очевидно, я подумал, что просто объясню, если кто-то, кто запутался, заглянет внутрь

Cikica
источник
1

Вы также можете всегда использовать более общий подход, не ища конкретную реализацию функции (то есть, не проверяя, проходит ли add_settings_section что-то неявно). Этот общий подход использует закрытие PHP.

Как его использовать: в любом месте, где вы передаете имя функции, вместо нее передается анонимная функция, с использованием в ней.

Пример:

вместо того

foreach ( $ar as $name => value ) {
    add_settings_section(
        $section,
        'something',
        'something-else',
        'callback_name'
    );
}

function callback_name() {
    do_something();
}

ты можешь использовать:

foreach ( $ar as $name => value ) {
    add_settings_section(
        $section,
        'something',
        'something-else',
        function () use ( $name, $value ) {
            callback_name( $name, $value )
        }
    );
}

function callback_name( $name, $value ) {
    do_something( $name, $value );
}
Ольга Фарбер
источник