Übergabe eines Parameters an Filter- und Aktionsfunktionen

52

Ist eine Möglichkeit, meine eigenen Parameter an die Funktion in add_filteroder zu übergeben add_action. Schauen Sie sich zum Beispiel den folgenden Code an:

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

Kann ich meinen eigenen Parameter übergeben? so etwas wie:

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

oder

add_filter('the_content', 'my_content', 10, 1, $my_param)
Aakash Chakravarthy
quelle

Antworten:

78

Standardmäßig ist dies nicht möglich. Es gibt Problemumgehungen, wenn Sie es auf die OOP-Weise tun.
Sie können eine Klasse erstellen, um die Werte zu speichern, die Sie später verwenden möchten.

Beispiel:

/**
 * 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 )
            )
        );
    }
}

Jetzt können Sie die Klasse mit jeder gewünschten Funktion aufrufen - wenn die Funktion irgendwo existiert, wird sie mit Ihren gespeicherten Parametern aufgerufen.

Lassen Sie uns eine Demo-Funktion erstellen ...

/**
 * 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>';
}

... und benutze es einmal ...

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

… und wieder …

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

Ausgabe:

Bildbeschreibung hier eingeben

Der Schlüssel ist die Wiederverwendbarkeit : Sie können die Klasse (und in unseren Beispielen auch die Funktion) wiederverwenden.

PHP 5.3+

Wenn Sie eine PHP - Version 5.3 oder höher verwenden , können Verschlüsse werden so viel einfacher machen:

$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>";
}

Der Nachteil ist, dass Sie keine Komponententests für Verschlüsse schreiben können. 

fuxia
quelle
17
Sie erhalten nicht nur eine positive Bewertung für eine qualitativ hochwertige Antwort auf ein Problem, für das eine integrierte Lösung im WP-Kern vorhanden sein sollte , sondern auch eine, wenn Sie fünf Monate später zurückkehren, um Ihre Antwort mit dem Abschlussbeispiel von PHP 5.3+ zu aktualisieren.
Adam
1
Hervorragende Antwort! Aber wie kann ich diesen von dieser anonymen Funktion erstellten Filter später entfernen?
Vinicius Tavares
2
@ViniciusTavares Das kannst du nicht. Überlegen Sie, bevor Sie es verwenden. :)
fuxia
5
Beachten Sie jedoch, dass Sie die anonyme Funktion, wenn Sie sie in einer Variablen speichern (z. B. $func = function() use ( $param1 ) { $param1; };und add_action( $func, 11);), überremove_action( $func, 11 );
bonger
1
Es ist jedoch nicht ratsam, anonyme Funktionen für Plugins oder Themes zu verwenden, die Sie für die Welt freigeben (Sie können sie für Ihre eigenen Projekte verwenden). Das Problem dabei ist, dass Sie sie nicht aushängen können. Welchen Ansatz Sie auch immer wählen, er sollte später nicht mehr einhakbar sein.
Mueyiwa Moses Ikomi
1

Erstellen Sie eine Funktion mit den erforderlichen Argumenten, die eine Funktion zurückgibt. Übergeben Sie diese Funktion (anonyme Funktion, auch als Closure bezeichnet) an den wp-Hook.

Hier gezeigt für einen Admin-Hinweis im WordPress-Backend.

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);
Hornament
quelle
1

Verwenden Sie PHP Anonymous-Funktionen :

$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);
wesamly
quelle
1

Ich weiß, dass die Zeit vergangen ist, aber ich hatte ein Problem mit der Übergabe meines eigenen Parameters, bis ich feststellte, dass der vierte Parameter in add_filter die Anzahl der übergebenen Parameter einschließlich des zu ändernden Inhalts ist. Wenn Sie also 1 zusätzlichen Parameter übergeben, sollte die Zahl 2 und in Ihrem Fall nicht 1 sein

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

und mit

function my_content($content, $my_param) {...}
Giacoder
quelle
1

Die korrekte, wirklich kurze und effizienteste Methode, um beliebig viele Argumente an WP-Filter und -Aktionen zu übergeben, ist die von @Wesam Alalem hier verwendete Methode , die den Abschluss verwendet.

Ich möchte nur hinzufügen, dass Sie es noch klarer und flexibler gestalten könnten, indem Sie die eigentliche Methode des Handlers von der anonymen Schließung trennen. Dazu rufen Sie die Methode aus dem Closure wie folgt auf (modifiziertes Beispiel aus @Wesam Alalem answer).

Auf diese Weise können Sie so lange oder komplizierte Logik schreiben, wie Sie möchten, und zwar außerhalb des Abschlusses, den Sie verwenden, um den eigentlichen Handelnden aufzurufen.

// ... 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;
}
bob-12345
quelle
0

Wenn Sie einen eigenen Hook erstellen, finden Sie hier ein Beispiel.

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

dann implementiere hook:

// [ https://codex.wordpress.org/Function_Reference/apply_filters ]
echo apply_filters( 'filter_name', $first, $second, $third );
T.Todua
quelle
Hiermit werden keine Informationen von der Registrierung an den Rückruf weitergegeben. Hier steht nur, wie viele Parameter der Callback annehmen kann.
fuxia
@fuxia, kannst du eine einfache Änderung vorschlagen, damit die Informationen weitergegeben werden? Würde man einfach die Parameterwerte nach dem anheften 3?
SherylHohman
0

Sie können immer global verwenden, nicht wahr?

  global $my_param;
samjco
quelle
Dies gibt keine Antwort auf die Frage. Sobald Sie über eine ausreichende Reputation verfügen, können Sie jeden Beitrag kommentieren . Geben Sie stattdessen Antworten an, die nicht vom Fragesteller geklärt werden müssen . - Aus der Bewertung
cjbj
@cjbj Tatsächlich. Die Frage ist, ob Parameter an die "Funktion" übergeben werden können, die sich in add_filter oder add_action befindet. Es war nicht klar, ob der Benutzer es in der Funktion add_filter oder add_action selbst übergeben wollte, obwohl dies die Annahme ist. :)
samjco
0

Gehen Sie eleganter vor, obwohl Sie eine Funktion direkt aufrufen: Übergeben Sie eine anonyme Funktion als Rückruf.

Zum Beispiel:

Ich habe eine einzige Funktion, um den Titel, den Inhalt und den Auszug aus meinen Beiträgen zu übersetzen. Daher muss ich einige Argumente an diese Hauptfunktion weitergeben, die besagen, wer anruft.

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

Die Hauptfunktion translate_texterhält also so viele Parameter, wie ich möchte, nur weil ich eine anonyme Funktion als Rückruf übergeben habe.

Marcos Rezende
quelle
-1

Ich hatte gehofft, dasselbe zu tun, aber da dies nicht möglich ist, besteht eine einfache Umgehung darin, eine andere Funktion wie aufzurufen add_filter('the_content', 'my_content_filter', 10, 1);

Dann kann my_content_filter () my_content () aufrufen und jedes gewünschte Argument übergeben.

Pierre-Verthume Larivière
quelle