Передача параметра для функції фільтра та дії


52

Це спосіб передавати власні параметри функції в add_filterабо add_action. Наприклад, подивіться у наступному коді:

function my_content($content, $my_param)
{
do something...
using $my_param here ...
return $content;
}
add_filter('the_content', 'my_content', 10, 1);

Чи можу я передати власний параметр? щось на зразок:

add_filter('the_content', 'my_content($my_param)', 10, 1)

або

add_filter('the_content', 'my_content', 10, 1, $my_param)

Відповіді:


78

За замовчуванням це неможливо. Є обхідні шляхи, якщо ви робите це OOP способом.
Ви можете створити клас для зберігання значень, які ви хочете використовувати пізніше.

Приклад:

/**
 * Stores a value and calls any existing function with this value.
 */
class WPSE_Filter_Storage
{
    /**
     * Filled by __construct(). Used by __call().
     *
     * @type mixed Any type you need.
     */
    private $values;

    /**
     * Stores the values for later use.
     *
     * @param  mixed $values
     */
    public function __construct( $values )
    {
        $this->values = $values;
    }

    /**
     * Catches all function calls except __construct().
     *
     * Be aware: Even if the function is called with just one string as an
     * argument it will be sent as an array.
     *
     * @param  string $callback Function name
     * @param  array  $arguments
     * @return mixed
     * @throws InvalidArgumentException
     */
    public function __call( $callback, $arguments )
    {
        if ( is_callable( $callback ) )
            return call_user_func( $callback, $arguments, $this->values );

        // Wrong function called.
        throw new InvalidArgumentException(
            sprintf( 'File: %1$s<br>Line %2$d<br>Not callable: %3$s',
                __FILE__, __LINE__, print_r( $callback, TRUE )
            )
        );
    }
}

Тепер ви можете зателефонувати до класу будь-якою функцією, яку ви хочете - якщо функція існує десь, вона буде викликатися зі збереженими параметрами.

Давайте створимо демонстраційну функцію ...

/**
 * Filter function.
 * @param  array $content
 * @param  array $numbers
 * @return string
 */
function wpse_45901_add_numbers( $args, $numbers )
{
    $content = $args[0];
    return $content . '<p>' . implode( ', ', $numbers ) . '</p>';
}

... і використовувати його один раз ...

add_filter(
    'the_content',
    array (
        new WPSE_Filter_Storage( array ( 1, 3, 5 ) ),
        'wpse_45901_add_numbers'
    )
);

… і знову …

add_filter(
    'the_content',
    array (
        new WPSE_Filter_Storage( array ( 2, 4, 6 ) ),
        'wpse_45901_add_numbers'
    )
);

Вихід:

введіть тут опис зображення

Ключ повторної використання : Ви можете повторно використовувати клас (а в наших прикладах також функцію).

PHP 5.3+

Якщо ви можете використовувати PHP версії 5.3 або новіші закриття , це значно полегшить:

$param1 = '<p>This works!</p>';
$param2 = 'This works too!';

add_action( 'wp_footer', function() use ( $param1 ) {
        echo $param1;
    }, 11 
);
add_filter( 'the_content', function( $content ) use ( $param2 ) {
        return t5_param_test( $content, $param2 );
    }, 12
);

/**
 * Add a string to post content
 *
 * @param  string $content
 * @param  string $string This is $param2 in our example.
 * @return string
 */
function t5_param_test( $content, $string )
{
    return "$content <p><b>$string</b></p>";
}

Мінусом є те, що ви не можете писати одиничні тести на закриття. 


17
Ви не тільки отримуєте підсумковий голос за якісну відповідь на проблему, яка повинна мати вбудоване рішення в ядрі WP , ви також отримаєте відповідне повернення через п’ять місяців, щоб оновити свою відповідь прикладом закриття PHP 5.3+.
Адам

1
Відмінна відповідь! Але як я можу потім пізніше видалити цей фільтр, створений цією анонімною функцією?
Vinicius Tavares

2
@ViniciusTavares Ви не можете. Подумайте, перш ніж використовувати його. :)
fuxia

5
Зауважте, що якщо ви збережете анонімну функцію до змінної (наприклад, $func = function() use ( $param1 ) { $param1; };і add_action( $func, 11);), її можна видалити за допомогоюremove_action( $func, 11 );
bonger

1
Але не бажано використовувати анонімні функції на плагінах або темах, які ви випускаєте у світ (ви можете використовувати їх у власних проектах). Проблема в тому, що ви не зможете їх зняти. Що ви коли-небудь підходите, з яким ви вирішите піти, слід пізніше зняти його.
Mueyiwa Мойсей Ікомі

1

Створіть функцію з необхідними аргументами, яка повертає функцію. Передайте цю функцію (анонімна функція, також відома як закриття) на гачок wp.

Показано тут для повідомлення адміністратора у програмі Wordpress.

public function admin_notice_func( $message = '')
{
$class = 'error';
    $output = sprintf('<div class="%s"><p>%s</p></div>',$class, $message);
    $func = function() use($output) { print $output; };
    return $func;
}
$func = admin_notice_func('Message');
add_action('admin_notices', $func);

1

Використовуйте функції php Anonymous :

$my_param = 'my theme name';
add_filter('the_content', function ($content) use ($my_param) {
    //$my_param is available for you now
    if (is_page()) {
        $content = $my_param . ':<br>' . $content;
    }
    return $content;
}, 10, 1);

1

Я знаю, що минув час, але у мене виникли проблеми з передачею власного параметра, поки я не виявив, що четвертий параметр у add_filter - це кількість переданих параметрів, включаючи зміст, який потрібно змінити. Тож якщо ви передасте 1 додатковий параметр, у вашому випадку число повинно бути 2, а не 1

add_filter('the_content', 'my_content', 10, 2, $my_param)

і використання

function my_content($content, $my_param) {...}

1

Правильний, дійсно короткий і найефективніший спосіб передачі будь-якої кількості аргументів до WP-фільтрів і дій є від @Wesam Alalem тут , який використовує закриття.

Я хотів би лише додати, що ви можете зробити це ще зрозумілішим та набагато гнучкішим, відокремивши фактичний метод виконання від анонімного закриття. Для цього ви просто викликаєте метод із закриття наступним чином (модифікований приклад з відповіді @Wesam Alalem).

Таким чином, ви можете записати таку довгу або складну логіку, як хочете, лексично поза межами закриття, яке ви використовуєте для виклику фактичного виконавця.

// ... inside some class

private function myMethod() {
    $my_param = 'my theme name';
    add_filter('the_content', function ($content) use ($my_param) {
        // This is the anonymous closure that allows to pass 
        // whatever number of parameters you want via 'use' keyword.
        // This is just oneliner.
        // $my_param is available for you now via 'use' keyword above
        return $this->doThings($content, $my_param);
    }, 10, 2);
}

private function doThings($content, $my_param) {
    // Call here some other method to do some more things
    // however complicated you want.
    $morethings = '';
    if ($content = 'some more things') {
        $morethings = (new MoreClass())->get();
    }
    return $my_param . ':<br>' . $content . $morethings;
}

0

якщо ви створюєте власний гачок, ось приклад.

// lets say we have three parameters  [ https://codex.wordpress.org/Function_Reference/add_filter ]
add_filter( 'filter_name', 'my_func', 10, 3 );
my_func( $first, $second, $third ) {
  // code
}

потім реалізуйте гачок:

// [ https://codex.wordpress.org/Function_Reference/apply_filters ]
echo apply_filters( 'filter_name', $first, $second, $third );

Це не передає інформацію від реєстрації до зворотного дзвінка. Він просто говорить, скільки параметрів може прийняти зворотний дзвінок.
фуксія

@fuxia, ви можете запропонувати просту зміну, щоб інформація пройшла? Можна було б просто доторкнутися до значень параметри після 3?
Шерил Хохман

0

Ви завжди можете використовувати глобальний, чи не так?

  global $my_param;

Це не дає відповіді на запитання. Коли у вас буде достатня репутація, ви зможете коментувати будь-яку публікацію ; натомість надайте відповіді, які не потребують уточнення від запитувача . - З огляду
cjbj

@cjbj Насправді це так. Питання полягає в тому, чи можна передати параметри "функції", яка знаходиться у add_filter або add loader. Не було зрозуміло, чи бажає користувач передати його у функцію add_filter або addcharge, хоча це припущення. :)
samjco

0

Незважаючи на виклик функції безпосередньо, зробіть це більш елегантно: передайте анонімну функцію як зворотний дзвінок.

Наприклад:

У мене є одна функція перекладати заголовок, зміст та уривок із своїх публікацій. Отже, мені потрібно передати цій головній функції кілька аргументів, які говорять про те, хто дзвонить.

add_filter( 'the_title', function( $text ) { 
    return translate_text( $text, 'title', 'pl' );
});

add_filter( 'the_content', function( $text ) { 
    return translate_text( $text, 'content', 'pl' );
});

add_filter( 'the_excerpt', function( $text ) { 
    return translate_text( $text, 'excerpt', 'pl' );
});

Отже, основна функція translate_textотримує стільки параметрів, скільки я хочу, тільки тому, що я передала анонімну функцію як зворотний виклик.


-1

Я сподівався зробити те саме, але оскільки це неможливо, я думаю, що простим способом вирішити проблему є виклик іншої функції на кшталт add_filter('the_content', 'my_content_filter', 10, 1);

тоді my_content_filter () може просто викликати my_content (), передаючи будь-який аргумент, який він хоче.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.