フィルターおよびアクション関数にパラメーターを渡す


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コア内に組み込みのソリューション必要な問題に対する質の高い回答を得るだ​​けでなく、5か月後に戻ってPHP 5.3+クロージャーの例で回答を更新するための回答を得ることができます。
アダム

1
素晴らしい答えです!しかし、この匿名関数によって作成されたこのフィルターを後で削除するにはどうすればよいですか?
ビニシウスタバレス14

2
@ViniciusTavaresできません。使用する前に考えてください。:)
fuxia

5
注しかし、あなたが変数に無名関数を保存する場合こと(例えば$func = function() use ( $param1 ) { $param1; };add_action( $func, 11);)あなたは経由して、それを削除することができますremove_action( $func, 11 );
bonger

1
ただし、世界にリリースするプラグインまたはテーマで匿名関数を使用することはお勧めできません(独自のプロジェクトで使用できます)。これの問題は、それらを外すことができないということです。どのアプローチを選択しても、後でフック解除できるはずです。
ムエイワモーゼス生見

1

関数を返す必要な引数を使用して関数を作成します。この関数(匿名関数、クロージャーとも呼ばれます)をwpフックに渡します。

ここに表示されているのは、ワードプレスバックエンドでの管理通知です。

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 匿名関数を使用します

$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の4番目のパラメーターが、変更する内容を含む渡されたパラメーターの数であることが判明するまで、自分のパラメーターを渡すことに問題がありました。したがって、1つの追加パラメーターを渡す場合、数は1でなく2でなければなりません

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

@fuxia、情報が渡されるように簡単な変更を提案できますか?後にパラメータ値を追加するだけ3ですか?
シェリルホーマン

0

いつでもグローバルを使用できますか?

  global $my_param;

これは質問に対する答えを提供しません。十分な評判たら、投稿コメントできるようになります。代わりに、askerからの説明を必要としない回答を提供してください。- レビューから
cjbj

@cjbj実際にはそうです。問題は、add_filterまたはadd_actionにある「関数」にパラメーターを渡すことができるかどうかです。ユーザーがadd_filter関数またはadd_action関数自体でそれを渡すことを望んでいるかどうかは、それが仮定である場合でも明確ではありませんでした。:)
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()を呼び出すことができます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.