Функция apply_filters_ref_array в WordPress: обзор и примеры использования

apply_filters_ref_array() │ WP 3.0.0

Функция apply_filters_ref_array() выполняет функции, связанные с определённым фильтром, и принимает аргументы в виде массива.

Возвращаемое значение

Смешанное. Отфильтрованное значение после применения всех связанных функций.

Использование

apply_filters_ref_array( $hook_name, $args );
  • $hook_name (строка) (обязательный) — имя фильтра.
  • $args (массив) (обязательный) — аргументы, переданные функциям, связанным с фильтром.

Примеры

Пример 1: Передача параметров

$args = array( 'arg_1', true, 'foo', 'arg_4' );
$arg_1 = apply_filters_ref_array( 'my_filter', $args );

Это эквивалентно следующему коду:

$arg_1 = apply_filters( 'my_filter', 'arg_1', true, 'foo', 'arg_4' );

Пример 2: Добавление функции к фильтру

// Вызов фильтра
$filtered = apply_filters_ref_array( 'my_filter', [ 10, 2, 3 ] ); //> 10

// Теперь прикрепим функцию
add_filter( 'my_filter', 'my_filter_func', 10, 3 ); // 3 - получаем 3 параметра

function my_filter_func( $var, $var2, $var3 ){
    return $var2 + $var3;
}

// Снова вызовем фильтр. Теперь к нему прикреплена функция my_filter_func()
$filtered = apply_filters_ref_array( 'my_filter', array( 10, 2, 3 ) ); //> 5

Пример 3: Передача переменных по ссылке

В этом примере мы передаем параметры в массиве, и первый параметр будет работать как обычный фильтр, т.е. прикрепленная функция должна вернуть его. Однако фильт�� сам вернёт только первый параметр массива — в данном случае переменную $orderby.

Также мы передаём переменную по ссылке во втором параметре, и функция my_filter_func() получает её по ссылке. Если мы изменим эту переменную внутри функции, она также изменится и снаружи.

// Прикрепляем функцию к фильтру
add_filter( 'my_filter', 'my_filter_func', 10, 2 );

function my_filter_func( $orderby, & $link ){
    // Изменяем параметр $link по ссылке
    $link = 'new val';

    // Изменяем параметр $orderby, как для обычного фильтра
    return 'DESC';
}

// Вызов фильтра разными способами

// Вызов 1 (всё работает как должно)
$link = 'old val';
echo apply_filters_ref_array( 'my_filter', [ 'ASC', & $link ] ); // DESC
echo $link; // new val

// Вызов 2 (НЕ работает - Ошибка парсинга)
$link = 'old val';
echo apply_filters( 'my_filter', 'ASC', & $link ); 
// Ошибка парсинга: неожиданный '&', ожидалось ')'

// Вызов 3 (НЕ работает - Предупреждение)
$link = 'old val';
$create_link = & $link;
echo apply_filters( 'my_filter', 'ASC', $create_link ); // DESC
// Предупреждение: Параметр 2 для my_filter_func() ожидается по ссылке
echo $link; // old val

Как мы видим, из всех вызовов, только первый работает корректно, где используется текущая функция apply_filters_ref_array().

Пример 4: Передача объекта в фильтр по ссылке

Этот пример показывает, что не обязательно использовать apply_filters_ref_array() для передачи объекта (экземпляра класса), но вы можете использовать основную функцию apply_filters(), когда требуется передать текущий объект $this.

Обратите внимание, что в прикрепленной функции не нужно указывать ссылку (& - просто $class, а не & $class), потому что объекты в PHP всегда передаются по ссылке.

class A {
    var $var = 'one';

    function __construct(){
        add_filter( 'my_filter', [ $this, 'filter_func' ], 10, 2 );
    }

    function filter_func( $orderby, $class ){
        // в этом случае не нужно указывать & для $class,
        // потому что объекты всегда передаются по ссылке!

        // изменяем объект
        $class->var = 'one';

        // изменяем параметр $orderby как для обычного фильтра
        return 'DESC';
    }

    function apply_filters_and_echo(){
        $orderby = apply_filters( 'my_filter', 'ASC', $this );

        var_dump( $orderby );   // string(4) "DESC"
        var_dump( $this->var ); // string(3) "one"
    }
}

// вызов класса
$class = new A();
$class->apply_filters_and_echo();

/* Результат:
string(4) "DESC"
string(3) "one"
*/

Заметки

  • Смотрите: apply_filters(). Эта функция идентична, но аргументы, передаваемые функциям, связанным с фильтром, передаются с помощью массива.
  • Глобальная переменная. $wp_filter[]. Хранит все фильтры и действия.
  • Глобальна�� переменная. $wp_filters[]. Считывает количество раз, когда каждый фильтр был вызван.
  • Глобальная переменная. $wp_current_filter[]. Содержит список текущих фильтров с последним текущим.

Журнал изменений

С версии 3.0.0 добавлено в WordPress.

Код функции

function apply_filters_ref_array( $hook_name, $args ) {
    global $wp_filter, $wp_filters, $wp_current_filter;

    if ( ! isset( $wp_filters[ $hook_name ] ) ) {
        $wp_filters[ $hook_name ] = 1;
    } else {
        ++$wp_filters[ $hook_name ];
    }

    // Сначала выполняем все действия 'all'.
    if ( isset( $wp_filter['all'] ) ) {
        $wp_current_filter[] = $hook_name;
        $all_args            = func_get_args(); // phpcs:ignore PHPCompatibility.FunctionUse.ArgumentFunctionsReportCurrentValue.NeedsInspection
        _wp_call_all_hook( $all_args );
    }

    if ( ! isset( $wp_filter[ $hook_name ] ) ) {
        if ( isset( $wp_filter['all'] ) ) {
            array_pop( $wp_current_filter );
        }

        return $args[0];
    }

    if ( ! isset( $wp_filter['all'] ) ) {
        $wp_current_filter[] = $hook_name;
    }

    $filtered = $wp_filter[ $hook_name ]->apply_filters( $args[0], $args );

    array_pop( $wp_current_filter );

    return $filtered;
}

Теперь у вас есть подробное объяснение функции apply_filters_ref_array() в WordPress, а также примеры её использования.

Leave a Reply

Ваш адрес email не будет опубликован. Обязательные поля помечены *