web-dev-qa-db-fra.com

Passer un paramètre aux fonctions de filtrage et d'action

Est un moyen de passer mes propres paramètres à la fonction dans add_filter ou add_action. Par exemple, jetez un oeil dans le code suivant:

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

Puis-je passer mon propre paramètre? quelque chose comme:

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

ou

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

Par défaut, cela n'est pas possible. Il existe des solutions de contournement si vous le faites de la manière OOP.
Vous pouvez créer une classe pour stocker les valeurs que vous souhaitez utiliser ultérieurement.

Exemple:

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

Vous pouvez maintenant appeler la classe avec la fonction de votre choix. Si la fonction existe quelque part, elle sera appelée avec vos paramètres stockés.

Créons une fonction de démonstration…

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

… Et l'utiliser une fois…

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

… et encore …

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

Sortie:

enter image description here

La clé est réutilisabilité : Vous pouvez réutiliser la classe (et dans nos exemples également la fonction).

PHP 5.3+

Si vous pouvez utiliser un PHP version 5.3 ou une version plus récente de closures , cela facilitera grandement les choses:

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

L'inconvénient est que vous ne pouvez pas écrire de tests unitaires pour les fermetures.

76
fuxia

Le moyen correct, très court et le plus efficace de passer tout nombre d'arguments à WP filtres et actions est de @Wesam Alalem here , qui utilise la fermeture.

J'ajouterais simplement que vous pourriez rendre la chose encore plus claire et beaucoup plus souple en séparant la méthode de l'auteur effectif de la fermeture anonyme. Pour cela, il vous suffit d'appeler la méthode à partir de la fermeture de la manière suivante (exemple modifié de @Wesam Alalem answer).

De cette façon, vous pouvez écrire une logique aussi longue ou compliquée que vous le souhaitez en dehors de la fermeture que vous utilisez pour appeler l'acteur réel.

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

Créez une fonction avec les arguments nécessaires qui retourne une fonction. Passez cette fonction (fonction anonyme, également appelée fermeture) au crochet wp.

Montré ici pour un avis d'administrateur dans le backend de 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
hornament

Utilisez php Fonctions anonymes :

$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
wesamly

Je sais que le temps a passé, mais j'ai eu un problème avec le passage de mon propre paramètre jusqu'à ce que je trouve que le 4ème paramètre de add_filter est le nombre de paramètres passés incluant le contenu à changer. Donc, si vous passez 1 paramètre supplémentaire, le nombre doit être 2 et non pas 1 dans votre cas

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

et en utilisant

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

Vous pouvez toujours utiliser global, n'est-ce pas?

  global $my_param;
0
samjco

si vous créez votre propre crochet, voici un exemple.

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

puis mettre en place le crochet:

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