web-dev-qa-db-fra.com

Implémentation des wrappers de fonctions add_ * avancées

add_action() et add_filter() sont des fonctions majeures. Cependant, dans certains scénarios , l'ajout d'une fonction supplémentaire et son accrochage quelque part deviennent encombrants et peu pratiques.

J'avais déterminé pour moi plusieurs cas d'utilisation pouvant rationaliser le code avec des wrappers s'ajoutant aux fonctions add_*. Les choses qui sont mieux gérées avec single-liner que des fonctions supplémentaires à chaque fois.

  1. Ajoutez un retour de filtre arbitraire . Il existe déjà des fonctions __return_* mais elles sont très limitées par définition. Pourquoi ne pas simplement passer ce que vous voulez retourner dans le filtre. Sauve de myriade function return_stuff(){return 'stuff';}

  2. Remplacez X par Y dans le filtre . Sauve de myriade function replace_stuff(){return str_replace();}

  3. Ajoutez une action avec des arguments arbitraires . Les actions se déclenchent avec des arguments, passés entre crochets. Mais parfois, vous ne vous souciez pas de cela et vous voulez simplement exécuter votre fonction avec vos propres arguments à un crochet spécifique. Sauve de myriade function echo_stuff(){echo 'stuff'}; et plus.

Alors...

  • Y a-t-il d'autres cas d'utilisation que vous souhaitez et/ou utilisez dans la pratique?

  • Comment mettriez-vous en œuvre de tels wrappers? Il y a beaucoup d'approches possibles (fermetures, variables globales pour garder des arguments supplémentaires, passer des objets dans un rappel, etc.).

PS J'ai plusieurs implémentations différentes pour (1) et (3) déjà et (comme suggéré) postera des morceaux de mon code un peu plus tard pour que je ne gâche pas le plaisir. :)

Exemple

Manière actuelle:

add_filter('wp_feed_cache_transient_lifetime', 'change_transient_lifetime', 10);

function change_transient_lifetime($lifetime) {

    return 3600;
}

Wrapper:

add_filter_return('wp_feed_cache_transient_lifetime', 10, 3600);
5
Rarst

J'avais publié mon code sous forme de bibliothèque Advanced Hooks API .

Quelques exemples:

add_action_with_arguments('test', 'printf', 10, 'boo%s', '<br />');
do_action('test');
// boo

add_filter_return('test2',10,'boo');
echo apply_filters('test2','not boo') . '<br />';
// boo

add_filter_append('test3',10,' and boo');
echo apply_filters('test3','boo') . '<br />';
// boo and boo

add_filter_prepend('test4',10,'boo and ');
echo apply_filters('test4','boo') . '<br />';
// boo and boo

add_filter_replace('test5','boo','you thought...');
echo apply_filters('test5','boo');
// you thought...
5
Rarst

Pour les cas simples comme les retours rapides sur une ligne, il convient de rappeler qu’il est possible d’attacher une fonction anonyme directement dans l’appel d’ajout de filtre, par exemple:

add_filter('some_filter_hook', function($v){return str_replace('..', '.', $v);});

add_action('some_action_hook', function(){echo '....';});
6
wyrfel

Vous voudrez peut-être examiner les méthodes de classes magiques et la surcharge en PHP pour lesquelles le nom de la fonction appelé est passé en tant que paramètre. Ensuite, vous pouvez prendre des décisions en fonction du nom de la fonction, comme return__some_string. J'identifie un code exemplaire et non testé:

class magiCall {
    public static function __callStatic ( string $name , array $arguments ) {
        // your code here, $name is the function name called.
    }
}

add_filter('hookname', 'magiCall::return__the_string');

Je pense que cet exemple montre assez bien l'idée.

Celui-ci est PHP 5.3.x, vous pouvez rendre ce PHP 5.2 compatible en utilisant la méthode magique __call. Si vous disposez d'une fonction publique statique pour renvoyer le rappel, vous pourrez alors pour l'écrire comparable simplifié. Voir le lien vers le manuel php ci-dessus.

5
hakre

Fonctions publicitaires anonymes ou lambda) Dans tous les cas, je les éviterais, car vous ne connaîtrez pas le nom de cet outil ni obtiendrez une sortie assez cryptée si vous inspectez un accrocher plus tard. Déboguer serait une douleur.

Ad votre A) L'approche est agréable et offre une API assez simple (+1).

Ad @hakre A) J'utilise à peu près la même fonction [1] dans mon coeur de framework - étendu par "set_" & une exception - pour définir et obtenir des variables à la volée. De cette façon, je n'ai qu'à étendre cette classe avec une classe enfant qui ressemble à une interface "uniquement variable" (celles qui doivent être disponibles). C'est une approche agréable et organisée qui ne conserve que des éléments dans les fichiers ne servant qu'une seule tâche. Avec quelque chose comme cela, vous pouvez peut-être éviter d'écrire des fonctions spécifiques pour chaque tâche comme "remplacer", etc.

[1] Code - Je lance tout le temps pour que vous puissiez l'appeler "testé - et fonctionne"

/**
 * Magic getter/setter method
 * Guesses for a class variable & calls/fills it or throws an exception.
 * Note: Already defined methods override this method.
 * 
 * Original @author Miles Keaton <[email protected]> 
 * on {@link http://www.php.net/manual/de/language.oop5.overloading.php#48440}
 * The function was extended to also allow 'set' tasks/calls and throws an exception.
 * 
 * @param (string) $name | Name of the property
 * @param unknown_type $args | arguments the function can take
 */
function __call( $name, $args )
{
    $_get = false;

    // See if we're calling a getter method & try to guess the variable requested
    if( substr( $val, 0, 4 ) == 'get_' )
    {
        $_get = true;
        $varname = substr( $val, 4 );
    }
    elseif( substr( $val, 0, 3 ) == 'get' )
    {
        $_get = true;
        $varname = substr( $val, 3 );
    }

    // See if we're calling a setter method & try to guess the variable requested
    if( substr( $val, 0, 4 ) == 'set_' )
    {
        $varname = substr( $val, 4 );
    }
    elseif( substr( $val, 0, 3 ) == 'set' )
    {
        $varname = substr( $val, 3 );
    }

    if ( ! isset( $varname ) )
        return new Exception( sprintf( __( "The method %1$s doesn't exist" ), "<em>{$val}</em>" ) );

    // Now see if that variable exists:
    foreach( $this as $class_var => $class_var_value )
    {
        if ( strtolower( $class_var ) == strtolower( $varname ) )
        {
            // GET
            if ( $_get )
            {
                return $this->{$class_var};
            }
            // SET
            else 
            {
                return $this->{$class_var} = $x[0];
            }
        }
    }

    return false;
}
0
kaiser

Pour les valeurs de retour simples, vous n’avez pas besoin de beaucoup de fonctions supplémentaires. Il y a le pratique current_filter() . Vous pouvez l'utiliser à l'intérieur de vos propres fonctions.

Exemple

<?php # -*- coding: utf-8 -*-
/*
Plugin Name: Filter System From Mail
Description: Sets the WP from mail address to the first admin’s mail and the from name to blog name.
Version:     1.1
Author:      Thomas Scholz
Author URI:  http://toscho.de
License:     GPL
*/

if ( ! function_exists( 'filter_system_from_mail' ) )
{
    /**
     * First admin's e-mail address or blog name depending on current filter.
     *
     * @return string
     */
    function filter_system_from_mail()
    {
        return get_option( 'wp_mail_from' == current_filter()
            ? 'admin_email' : 'blogname' );
    }

    add_filter( 'wp_mail_from',      'filter_system_from_mail' );
    add_filter( 'wp_mail_from_name', 'filter_system_from_mail' );
}

Ou… ai-je mal interprété votre question?

0
fuxia