Jak wykonać czynność i uzyskać wartość zwrotu?

10

Jest więc następujący scenariusz.

Dodaję akcję, aby wyczyścić dzienniki z bazy danych:

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

Teraz chcę okresowo uruchamiać tę akcję:

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

i wykonaj ręcznie:

do_action( 'myplugin_clean_logs' );

Metoda MyPlugin_Logs::clean_logszwraca liczbę dotkniętych wierszy lub fałsz, jeśli coś poszło w innym kierunku.

Teraz chcę wyświetlić liczbę usuniętych wierszy. Wyobrażam sobie coś takiego:

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

Ale ponieważ do_actionnie zwróci żadnej wartości, nie mam pojęcia, jak uzyskać wartość zwracaną.

Czy powinienem wykonać metodę bezpośrednio podczas uruchamiania ręcznego, ale użyć tej akcji do zaplanowania zdarzeń?

Aley
źródło
1
Nie chcesz powtarzać niczego w zaplanowanym zdarzeniu, więc tak, wykonałbym tę metodę bezpośrednio podczas ręcznego uruchamiania (zakładam, że administrator uruchomiłby to i chcesz pokazać im wynik).
Tim Malone

Odpowiedzi:

13

Fajne jest to, że filtr jest taki sam jak akcja, tyle że zwraca wartość, więc po prostu ustaw go jako filtr:

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

Następnie coś takiego:

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

powinien przejść $affected_rowsdo clean_logs()(i wszelkich innych funkcji, do których można się przyczepić myplugin_clean_logs) i przypisać wartość zwracaną z powrotem do $affected_rows.

Caspar
źródło
4
nie jest to zalecane, ponieważ jest to hakowanie kodu zamiast tworzenia oprogramowania. Gdyby działania były tylko podzbiorem filtrów, nie byłoby takiej potrzeby. Cron nie może przekazać wartości, dlatego nie powinien być przechwytywany jako filtr, nawet jeśli błędny kod rdzenia pozwala robić takie shemigany :)
Mark Kaplun 21.04.16
1
Punkt wzięty. Rozumiem zamiar dwóch różnych rzeczy, ale aby spojrzeć na podstawowy kod tutaj, cała do_action()sprawa jest niczym więcej niż skomplikowanym hackiem apply_filters():)
Caspar
nie jedyny zły projekt w rdzeniu, który częściowo prowadzi do zamieszania, które prowadzi do takich pytań
Mark Kaplun
1
Musimy pracować z tym, co mamy, więc chociaż rozumiem punkt widzenia Marka, nadal uważam, że jest to prawidłowa odpowiedź - chyba że podstawowe zmiany zmienią to podejście w przyszłości, ale myślę, że jest to mało prawdopodobne z powodu ogromnych problemów z kompatybilnością wsteczną wprowadziłoby to.
Tim Malone
3
Dzięki, @TimMalone. Doceniam sprzeciw @ mark-kaplun. Moja odpowiedź opisuje, jak obejść do_action()problem, nie zwracając wartości, a nie jak zaprojektować rozwiązanie zgodne z do_action()intencją. Jeśli ktoś jest w stanie zrobić to, o co prosi, ta odpowiedź zasługuje na akceptację. Moją pierwszą myślą byłoby, aby metoda przechwycona (zakładając, że OP używa projektu OOP dla tej wtyczki) upuściła wynik w chronionej właściwości klasy wtyczki, a następnie napisała szybki getter, aby wyciągnąć ją w późniejszym czasie. Ale to tylko dziki pomysł!
Caspar
-1

Nigdy nie korzystałem z tej funkcji i nie testowałem jej, ale czy może ona działać? 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);

Jeśli to nie zadziała, może po prostu odfiltruj coś, co sugerował Caspar? Chodzi mi o to, że taki jest cel filtra, a w tym przypadku liczba dotkniętych wierszy jest filtrowana. (Tęsknię za starym MortCore. Czy ktoś pamięta, jak obsługiwał zwracane wartości, przekazywanie referencji i argumenty za pomocą tylko jednej funkcji trzech parametrów?)

Goofball
źródło
To okropna odpowiedź, ponieważ przekazywanie i modyfikowanie wartości przez odniesienie jest naprawdę złą praktyką. Szczerze mówiąc, ta odpowiedź naprawdę nie zapewnia wartości w kontekście pytania i prawdopodobnie powinna zostać usunięta lub zmieniona w komentarz. Ponadto korzystanie z anonimowych funkcji z zaczepami jest również złą praktyką, ponieważ uniemożliwia ich odczepienie.
Hybrid Web Dev
Zgadzam się z tych samych wyżej wymienionych powodów, że nie jest to zalecana ścieżka. Jeśli z jakiegoś powodu potrzebujesz uzyskać wartość zwrotną z akcji i potrzebujesz czegoś szybkiego i brudnego, wolałbym rozwiązanie Caspars. Jeśli rozwijasz coś z wyprzedzeniem cyklu życia, szukałbym bardziej solidnego sposobu. Zastanawiasz się, co powiesz na powiadomienia administracyjne? developer.wordpress.org/reference/hooks/admin_notices
jgangso