Wie mache ich eine Aktion und erhalte einen Rückgabewert?

10

Es gibt also das folgende Szenario.

Ich füge eine Aktion hinzu, um Protokolle aus der Datenbank zu bereinigen:

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

Jetzt möchte ich diese Aktion regelmäßig ausführen:

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

und führen Sie es manuell aus:

do_action( 'myplugin_clean_logs' );

Die Methode MyPlugin_Logs::clean_logsgibt die Anzahl der betroffenen Zeilen oder false zurück, wenn etwas in die andere Richtung gegangen ist.

Jetzt möchte ich die Anzahl der gelöschten Zeilen anzeigen. Ich würde mir so etwas vorstellen:

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

Da do_actionjedoch kein Wert zurückgegeben wird, habe ich keine Ahnung, wie der Rückgabewert ermittelt werden soll.

Sollte ich die Methode direkt in einem manuellen Lauf ausführen, aber die Aktion für geplante Ereignisse verwenden?

Aley
quelle
1
Sie möchten bei einem geplanten Ereignis nichts wiedergeben, also würde ich die Methode direkt bei einem manuellen Lauf ausführen (ich gehe davon aus, dass der Administrator dies auslösen würde, und Sie möchten ihnen die Ausgabe anzeigen).
Tim Malone

Antworten:

11

Das Coole daran ist, dass ein Filter mit einer Aktion identisch ist, nur dass er einen Wert zurückgibt. Richten Sie ihn stattdessen als Filter ein:

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

Dann so etwas wie:

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

sollte $affected_rowsan clean_logs()(und an alle anderen Funktionen, an die Sie sich angeschlossen haben myplugin_clean_logs) übergeben werden und den Rückgabewert zurück anweisen $affected_rows.

Caspar
quelle
4
Downvoted, da dies Code hackt, anstatt Software zu entwickeln. Wenn Aktionen nur eine Teilmenge von Filtern wären, wären sie nicht erforderlich gewesen. Cron kann keinen Wert dafür übergeben, es sollte nicht als Filter eingehakt werden, selbst wenn der fehlerhafte Kerncode es Ihnen erlaubt, solche Shemigans zu machen :)
Mark Kaplun
1
Punkt genommen. Ich verstehe, dass die Absicht der beiden verschiedenen Dinge, aber um den Kerncode hier zu betrachten, ist das Ganze do_action()nichts weiter als ein aufwändiger Hack von apply_filters():)
Caspar
Nicht das einzige schlechte Design im Kern, das teilweise zu Verwirrung führt, die zu Fragen wie diesen führt
Mark Kaplun
1
Wir müssen mit dem arbeiten, was wir haben. Obwohl ich Marks Standpunkt verstehe, denke ich immer noch, dass dies eine legitime Antwort ist - es sei denn, der Kern ändert diesen Ansatz in Zukunft, aber ich denke, dass dies aufgrund der massiven Abwärtskompatibilitätsprobleme unwahrscheinlich ist es würde einführen.
Tim Malone
3
Danke, @ TimMalone. Ich schätze den Einwand von @ mark-kaplun. Meine Antwort beschreibt, wie man umgeht, do_action()ohne einen Wert zurückzugeben, anstatt eine Lösung zu entwerfen, die mit der do_action()Absicht übereinstimmt . Wenn jemand in der Lage ist, das zu tun, was er verlangt, verdient diese Antwort die akzeptierte Antwort. Mein erster Gedanke wäre, die Hooked-Methode (vorausgesetzt, das OP verwendet ein OOP-Design für dieses Plugin) das Ergebnis in eine geschützte Eigenschaft der Plugin-Klasse zu legen und dann einen Quick Getter zu schreiben, um es zu einem späteren Zeitpunkt herauszuholen. Aber das ist nur ein wildes Haar einer Idee!
Caspar
-1

Ich habe diese Funktion noch nie benutzt und noch nicht getestet, aber könnte sie funktionieren? 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);

Wenn das nicht funktioniert, warum nicht einfach das filtern, was Caspar vorgeschlagen hat? Ich meine, das ist der Zweck eines Filters, und in diesem Fall wird die Anzahl der betroffenen Zeilen gefiltert. (Ich vermisse den alten MortCore. Kann sich jemand daran erinnern, wie er Rückgabewerte, Referenzübergabe und Argumente mit nur einer einzigen Drei-Parameter-Funktion behandelt hat?)

Goofball
quelle
Dies ist eine schreckliche Antwort, da das Übergeben und Ändern von Werten durch Bezugnahme wirklich eine schlechte Praxis ist. Ehrlich gesagt bietet diese Antwort im Kontext der Frage wirklich keinen Wert und sollte wahrscheinlich entfernt oder in einen Kommentar geändert werden. Darüber hinaus ist die Verwendung anonymer Funktionen mit Hooks ebenfalls eine schlechte Praxis, da sie nicht ausgehängt werden können.
Hybrid Web Dev
Ich stimme aus den oben genannten Gründen zu, dass dies kein empfohlener Weg ist. Wenn Sie aus irgendeinem Grund einen Rückgabewert von einer Aktion benötigen und etwas schnelles und schmutziges benötigen, würde ich die Caspars-Lösung bevorzugen. Wenn Sie etwas mit einem Lebenszyklus vor sich entwickeln, würde ich nach einem robusteren Weg suchen. Wie wäre es mit Admin-Benachrichtigungen? developer.wordpress.org/reference/hooks/admin_notices
jgangso