Jak przekazać zmienną do wywołania zwrotnego add_settings_section ()?

16

Usiłuję zautomatyzować, w miarę możliwości, wywołania funkcji API ustawień dla każdego ustawienia we wtyczce. Pętla w tablicy opcji oraz wyprowadzanie add_settings_section()i add_settings_field()jest dość prosta:

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'
        );
    }
}

I `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
    );
}

Za pomocą add_settings_field()mogę łatwo napisać ogólne wywołanie zwrotne, przekazując $hookzmienną do wywołania zwrotnego, jako piąty parametr w wywołaniu funkcji:

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 
}

Wydaje się jednak, że add_settings_section()nie ma analogicznego $argsparametru; dlatego nie mogę użyć tej samej metody do przekazania $sectionzmiennej do wywołania zwrotnego.

Zatem moje pytanie: czy jest jakiś sposób przekazania zmiennej do add_settings_section()wywołania zwrotnego, czy jakiś inny sposób utworzenia wywołania zwrotnego analogicznego do tego, co robię add_settings_field()?

EDYTOWAĆ:

@Bainternet przybił go! Oto mój działający kod:

/**
 * 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
            }
        }
    }
}
Chip Bennett
źródło
1
Tylko sidenote: dlaczego nie extract( $args, EXTR_SKIP );na początku oenology_hooks_setting_callback(), więc nie musisz zapisywać każdej części tablicy w nowej $var? Będą one wówczas dostępne $'name_inside_the_arraynp. „$ title , $ tab” itp.
Kaiser
... bo tak naprawdę nie jestem aż tak inteligentny z PHP? :) Spróbuję; dzięki!
Chip Bennett
Być może chcesz rzucić okiem na tę Gist , która pokazuje przykład „być może najlepszej praktyki”, w jaki sposób dodawać filtry i haki, analizować argumenty i radzić sobie z wprowadzaniem ciągu zapytania. Jest trochę stary i prawdopodobnie go przerobię, kiedy będę miał czas, ale imo warto to zobaczyć. :)
kaiser
To właściwie tylko wtyczka, która dodaje interfejs użytkownika dla haków dodanych do enologii. Nie mam nic przeciwko temu, jak w rzeczywistości dodałem haki do motywu. Teraz staram się zapewnić wygodny sposób na udostępnienie ich użytkownikom końcowym.
Chip Bennett
Nie zrozumiałem cię. Chciałem ci tylko to pokazać, na wypadek, gdyby mógł ci pomóc (kiedykolwiek). Widzę ten kod jako coś ironicznego - wystarczy spojrzeć, ile wysiłku potrzeba, aby zdobyć wszystko dla wszystkich w formie wordpress ...
Kaiser

Odpowiedzi:

18

jeśli spojrzysz na funkcję do_settings_sections, a dokładniej na linię 1164, w której wykonywana jest funkcja zwrotna:

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

widać, że tablica sekcji $ jest przekazywana do funkcji zwrotnej, dzięki czemu można zidentyfikować wywołanie zwrotne za pomocą $section['id']

mam nadzieję, że tak się stanie.

Aktualizacja

oto przykład, jeśli nazwa twojego wywołania zwrotnego add_settings_section dla wszystkich sekcji została nazwana oenology_hooks_section_callback, możesz to zidentyfikować w następujący sposób:

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
    }
 }

a przez robienie rzeczy mam na myśli robienie, co chcesz zrobić z wywołaniem zwrotnym tej sekcji.

Bainternet
źródło
Hmm ... wygląda obiecująco. Jak ustalić $section['id']?
Chip Bennett
@Chip Bennett idbędzie pierwszym argumentem, który przekażeszadd_settings_section()
Rarst
@Chip Bennett Dodałem przykład, aby spróbować lepiej wyjaśnić.
Bainternet
@Bainternet: Awesome! Mam skrypt opcji i napotkałem ten sam problem, co Chip Bennett. Teraz działa jak urok. Dzięki.
Anh Tran
Okej, więc w końcu kliknęło w weekend; pozwól mi wypróbować kod, który mam na myśli, a ja zgłoś się.
Chip Bennett
4

Wiem, że to stare pytanie, ale wrzucę moje dwa centy, na wypadek, gdyby przyszedł ktoś inny; najprościej byłoby napisać własną modyfikację add_settings_section()funkcji, która dodawałaby tylko parametr args wywołania zwrotnego na końcu.

To by wyglądało tak (lub coś takiego)

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' );
}

Teraz wystarczy użyć tego zamiast natywnej funkcji wordpress i uzyskać dostęp do argumentów wywołania zwrotnego za pomocą 'callbackargs'klawisza tablicy w zwykły sposób, taki jak ten

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

Którego możemy użyć, aby przejść do innej funkcji:

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

Lub argumentami wywołania zwrotnego może być sama tablica, której używamy:

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

Jest to możliwe, ponieważ wszystko, co add_settings_section()robi, to dodanie nowego elementu tablicy do $wp_settings_sectionszmiennej globalnej, tym nowym elementem tablicy może być sama tablica zawierająca dowolną liczbę kluczy o różnych nazwach, z których mogłaby korzystać dowolna funkcja, która wiedziała, że ​​tam są. Kiedy do_settings_sectionsnazywa call_user_func_arrayto przechodzi $sectionsparamater jak zauważył Bainternet, oznacza to, że cała tablica dodaliśmy do $wp_settings_sectionsw my_add_settings_section()przepuszcza do naszego zwrotnego, co oznacza, że mamy dostęp do każdego nowego członka tablicy dodamy do niego takie jak callbackargspozwalając naszej funkcji, aby mieć pełny rozwinięty callback.

Chociaż jestem pewien, że może to być oczywiste, pomyślałem, że wytłumaczę to na wypadek, gdyby ktoś się zagubił.

Cikica
źródło
1

Zawsze możesz także zastosować bardziej ogólne podejście, nie szukając konkretnej implementacji funkcji (tzn. Bez sprawdzania, czy add_settings_section przekazuje cokolwiek pośrednio). To ogólne podejście wykorzystuje zamknięcie PHP.

Jak tego używać: w każdym miejscu, w którym przekazujesz nazwę funkcji, zamiast niej przekazujesz funkcję anonimową, z jej użyciem .

Przykład:

zamiast

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

function callback_name() {
    do_something();
}

możesz użyć:

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 );
}
Olga Farber
źródło