Как сделать do_action и получить возвращаемое значение?

10

Так что есть следующий сценарий.

Я добавляю действие для очистки журналов из базы данных:

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

Теперь я хочу периодически запускать это действие:

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

и выполнить его вручную:

do_action( 'myplugin_clean_logs' );

Метод MyPlugin_Logs::clean_logsвозвращает количество затронутых строк или false, если что-то пошло в другом направлении.

Теперь я хочу отобразить количество строк, которые были удалены. Я хотел бы представить что-то вроде этого:

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

Но так как do_actionне возвращает никакого значения, я понятия не имею, как получить возвращаемое значение.

Должен ли я выполнить метод непосредственно при ручном запуске, но использовать действие с расписанием событий?

Алей
источник
1
Вы не хотите, чтобы что-то повторялось на запланированном событии, поэтому да, я бы выполнял метод непосредственно при ручном запуске (я предполагаю, что администратор вызовет это, и вы хотите показать им вывод).
Тим Мэлоун

Ответы:

13

Круто то, что фильтр - это то же самое, что и действие, только он возвращает значение, поэтому просто установите его как фильтр:

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

Тогда что-то вроде:

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

должен пройти $affected_rowsк clean_logs()(и любые другие функции , которые вы , возможно, подключили к myplugin_clean_logs) и присвоить возвращаемое значение обратно $affected_rows.

Каспар
источник
4
пониженный голос, поскольку это - взламывание кода вместо разработки программного обеспечения. Если бы действия были просто подмножеством фильтров, в них не было бы необходимости. Cron не может передать значение для него, его не следует зацеплять как фильтр, даже если код ядра с ошибками позволяет вам делать такие шемиганы :)
Марк Каплун
1
Дело принято. Я понимаю, что цельdo_action() состоит в двух разных вещах, но если посмотреть на основной код здесь, то все это не более чем сложный взлом apply_filters():)
Caspar
не единственный плохой дизайн в ядре, что частично приводит к путанице, которая приводит к таким вопросам
Марк Каплун,
1
Нам нужно работать с тем, что у нас есть, поэтому, хотя я понимаю точку зрения Марка, я все же считаю, что это правильный ответ - если, конечно, ядро ​​не изменит этот подход в будущем, но я думаю, что это маловероятно из-за огромных проблем обратной совместимости это представило бы.
Тим Мэлоун
3
Спасибо, @TimMalone. Я ценю возражение @ mark-kaplun. Мой ответ описывает, как обойтись do_action()без возврата значения, а не как разработать решение в соответствии с do_action()намерением. Если кто-то может сделать то, что он просит, этот ответ заслуживает того, чтобы быть принятым ответом. Моей первой мыслью было бы, чтобы подключенный метод (предполагая, что OP использует дизайн ООП для этого плагина) перенес его результат в защищенное свойство класса плагина, а затем написал быстрый метод получения, чтобы вытащить его в какой-то более поздний момент. Но это просто дикая идея!
Каспар
-1

Никогда не использовал эту функцию и не проверял ее, но может ли она работать? 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);

Если это не сработает, почему бы просто не отфильтровать то, что предложил Каспар? Я имею в виду, что это цель фильтра, и в этом случае количество затронутых строк - это то, что фильтруется. (Я скучаю по старому MortCore. Кто-нибудь помнит, как он обрабатывал возвращаемые значения, передачу по ссылке и аргументы с помощью только одной трехпараметрической функции?)

Goofball
источник
Это ужасный ответ, поскольку передача и изменение значений по ссылке - очень плохая практика. Честно говоря, этот ответ на самом деле не дает значения в контексте вопроса и, вероятно, должен быть удален или изменен на комментарий. Кроме того, использование анонимных функций с хуками также является плохой практикой, поскольку их невозможно отсоединить.
Hybrid Web Dev
Я согласен по тем же вышеупомянутым причинам, что это не рекомендуемый путь. Если по какой-то причине вам необходимо получить возвращаемое значение из действия, и вам нужно что-то быстрое и грязное, я бы предпочел решение Caspars. Если вы разрабатываете что-то с жизненным циклом впереди, я бы искал более надежный путь. Подумайте о том, как насчет уведомлений администратора? developer.wordpress.org/reference/hooks/admin_notices
jgangso