Comment faire une action et obtenir une valeur de retour?

10

Il y a donc le scénario suivant.

J'ajoute une action pour nettoyer les journaux de la base de données:

add_action( 'myplugin_clean_logs', array( 'MyPlugin_Logs', 'clean_logs' ) );

Maintenant, je veux exécuter cette action périodiquement:

wp_schedule_event( current_time( 'timestamp' ), 'daily', 'myplugin_clean_logs' );

et l'exécuter manuellement:

do_action( 'myplugin_clean_logs' );

La méthode MyPlugin_Logs::clean_logsrenvoie le nombre de lignes affectées ou false si quelque chose va dans l'autre sens.

Maintenant, je veux afficher le nombre de lignes qui ont été supprimées. J'imagine quelque chose comme ça:

$affected_rows = do_action( 'myplugin_clean_logs' );
echo $affected_rows . ' entries have been deleted.';

Mais comme do_actionje ne retournerai aucune valeur, je ne sais pas comment obtenir la valeur de retour.

Dois-je exécuter la méthode directement sur une exécution manuelle, mais utiliser l'action sur les événements planifiés?

Aley
la source
1
Vous ne voulez pas faire écho à quoi que ce soit sur un événement planifié, alors oui, j'exécuterais la méthode directement sur une exécution manuelle (je suppose que l'administrateur déclencherait cela, et vous voulez leur montrer la sortie).
Tim Malone

Réponses:

11

Ce qui est cool, c'est qu'un filtre est identique à une action, seulement il renvoie une valeur, alors configurez-le simplement comme un filtre à la place:

add_filter( 'myplugin_clean_logs', array( 'MyPlugin_Logs', 'clean_logs' ) );

Ensuite, quelque chose comme:

$affected_rows = '';
$affected_rows = apply_filters( 'myplugin_clean_logs', $affected_rows );

doit passer $affected_rowsà clean_logs()(et quelles que soient les autres fonctions auxquelles vous avez pu vous connecter myplugin_clean_logs) et attribuer la valeur de retour à $affected_rows.

Caspar
la source
4
downvoted car il s'agit de pirater du code au lieu de développer un logiciel. Si les actions n'étaient qu'un sous-ensemble de filtres, il n'y en aurait pas eu besoin. Cron ne peut pas transmettre de valeur à cet effet, il ne doit pas être accroché en tant que filtre même si le code de base du buggy vous permet de faire de tels shemigans :)
Mark Kaplun
1
Point pris. Je comprends que l' intention des deux choses différentes, mais pour regarder le code principal ici, le tout do_action()n'est rien de plus qu'un hack élaboré de apply_filters():)
Caspar
pas le seul mauvais design dans le noyau qui est en partie ce qui conduit à la confusion qui conduit à des questions comme celle-ci
Mark Kaplun
1
Nous devons travailler avec ce que nous avons, donc bien que je comprenne le point de vue de Mark, je pense toujours que c'est une réponse légitime - à moins bien sûr que le noyau ne change cette approche à l'avenir, mais je pense que peu probable en raison des énormes problèmes de rétrocompatibilité cela introduirait.
Tim Malone
3
Merci, @TimMalone. J'apprécie l'objection de @ mark-kaplun. Ma réponse décrit comment contourner le do_action()problème sans renvoyer une valeur plutôt que comment concevoir une solution en accord avec l' do_action()intention de s. Si quelqu'un est capable de faire ce qu'il demande, cette réponse mérite d'être la réponse acceptée. Ma première pensée serait d'avoir la méthode hookée (en supposant que l'OP utilise une conception OOP pour ce plugin) déposer son résultat dans une propriété protégée de la classe du plugin, puis écrire un getter rapide pour le retirer ultérieurement. Mais ce n'est qu'une chevelure sauvage d'une idée!
Caspar
-1

Je n'ai jamais utilisé cette fonction et je ne l'ai pas testée, mais pourrait-elle fonctionner? do_action_ref_array () .

function myplugin_clean_logs_fn() {
    $args = array(
        'param1'        => 'val1',
        'param2'        => 'val2',
        'affected_rows' => 0,
    );
    do_action_ref_array( 'myplugin_clean_logs', &$args );
    return $args['affected_rows'];
}

// CALL IT
$affected_rows = my_plugin_clean_logs();
echo $affected_rows .' entr'. ($args['affected_rows']*1===1?'y':'ies') .' deleted.';

// SCHEDULE IT
add_action('myplugin_clean_logs_call_fn', 'myplugin_clean_logs_fn');
wp_schedule_event( current_time( 'timestamp' ), 'daily', 'myplugin_clean_logs_call_fn' );

// A SAMPLE FILTER
add_action('myplugin_clean_logs', function($args) {
    // Cleaning process
    // For each log affected, increment $args['affected_rows'] accordingly
}, 10, 3);

Si cela ne fonctionne pas, pourquoi ne pas simplement filtrer la chose comme l'a suggéré Caspar? Je veux dire, c'est le but d'un filtre, et dans ce cas, le nombre de lignes affectées est la chose filtrée. (L'ancien MortCore me manque. Quelqu'un se souvient-il de la façon dont il a géré les valeurs de retour, le passage par référence et les arguments avec une seule fonction à trois paramètres?)

Goofball
la source
C'est une réponse horrible, car passer et modifier des valeurs par référence est vraiment une mauvaise pratique. Honnêtement, cette réponse ne fournit vraiment aucune valeur dans le contexte de la question et devrait probablement être supprimée ou modifiée en commentaire. De plus, l'utilisation de fonctions anonymes avec des crochets est également une mauvaise pratique, car il est impossible de les décrocher.
Hybrid Web Dev
Je suis d'accord pour les mêmes raisons mentionnées ci-dessus, que ce n'est pas un chemin recommandé. Si, pour une raison quelconque, vous avez besoin d'obtenir une valeur de retour d'une action et que vous avez besoin de quelque chose de rapide et sale, je préférerais la solution Caspars. Si vous développez quelque chose avec un cycle de vie devant lui, je chercherais une manière plus robuste. En y pensant, que diriez-vous des avis d'administrateur? developer.wordpress.org/reference/hooks/admin_notices
jgangso