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

52

Est un moyen de passer mes propres paramètres à la fonction dans add_filterou 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)
Aakash Chakravarthy
la source

Réponses:

78

Par défaut, cela n'est pas possible. Il existe des solutions de contournement si vous le faites à la POO.
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:

entrez la description de l'image ici

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

PHP 5.3+

Si vous pouvez utiliser une version de PHP 5.3 ou plus récent fermetures feront beaucoup plus facile:

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

fuxia
la source
17
Non seulement vous obtenez un vote positif pour une réponse de qualité à un problème qui devrait avoir une solution intégrée dans le noyau WP , mais vous en obtenez une pour revenir cinq mois plus tard afin de mettre à jour votre réponse avec l'exemple de fermeture PHP 5.3+.
Adam
1
Excellente réponse! Mais comment puis-je supprimer ce filtre créé par cette fonction anonyme ultérieurement?
Vinicius Tavares
2
@ ViniciusTavares Vous ne pouvez pas. Réfléchissez avant de l'utiliser. :)
fuxia
5
Notez cependant que si vous enregistrez la fonction anonyme dans une variable (par exemple, $func = function() use ( $param1 ) { $param1; };et add_action( $func, 11);), vous pouvez la supprimer viaremove_action( $func, 11 );
bonger
1
Mais il n'est pas conseillé d'utiliser des fonctions anonymes sur les plugins ou les thèmes que vous publiez (vous pouvez les utiliser sur vos propres projets). Le problème avec ceci est que vous ne pourrez pas les décrocher. Quelle que soit l'approche que vous décidez de suivre, elle devrait être impossible à rattraper plus tard.
Mueyiwa Moses Ikomi
1

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);
hornament
la source
1

Utilisez les fonctions php 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);
wesamly
la source
1

Je sais que le temps a passé, mais j'ai eu du mal à passer mon propre paramètre jusqu'à ce que je découvre que le quatrième paramètre de add_filter est le nombre de paramètres transmis, y compris le contenu à modifier. 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) {...}
giacoder
la source
1

Le moyen correct, très court et le plus efficace de transmettre le nombre d'arguments aux filtres et actions de WP est de @Wesam Alalem ici , 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, lexicalement 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;
}
bob-12345
la source
0

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 );
T.Todua
la source
Cela ne transmet pas les informations de l'enregistrement au rappel. Il indique simplement le nombre de paramètres que le rappel peut accepter.
fuxia
@fuxia, pouvez-vous suggérer un changement simple pour que l'information soit transmise? Souhaitez-vous juste clouer sur les valeurs param après 3?
SherylHohman
0

Vous pouvez toujours utiliser global ne pourrait pas vous?

  global $my_param;
samjco
la source
Cela ne fournit pas de réponse à la question. Une fois que vous avez suffisamment de réputation, vous pourrez commenter n'importe quel message . au lieu de cela, fournissez des réponses qui ne nécessitent pas de clarification de la part du demandeur . - De l'avis
cjbj
@ cjbj En fait, c'est le cas. La question est de savoir si les paramètres peuvent être passés à la "fonction" qui se trouve dans add_filter ou add_action. Il n'était pas clair si l'utilisateur voulait le transmettre dans la fonction add_filter ou add_action elle-même, même si cela est l'hypothèse. :)
samjco
0

Malgré l'appel direct d'une fonction, procédez de manière plus élégante: transmettez une fonction anonyme en tant que rappel.

Par exemple:

J'ai une seule fonction pour traduire le titre, le contenu et l'extrait de mes articles. Il faut donc que je transmette à cette fonction principale des arguments indiquant qui appelle.

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

Ainsi, la fonction principale translate_textreçoit autant de paramètres que je souhaite, simplement parce que j'ai transmis une fonction anonyme en tant que rappel.

Marcos Rezende
la source
-1

J'espérais faire la même chose, mais comme ce n'est pas possible, une solution de contournement simple consiste à appeler une fonction différente, comme add_filter('the_content', 'my_content_filter', 10, 1);

alors my_content_filter () peut simplement appeler my_content () en transmettant n'importe quel argument.

Pierre-Verthume Larivière
la source