Wordpress фильтр для изменения окончательного вывода HTML

36

Wordpress имеет отличную поддержку фильтра для получения всех видов определенных бит контента и изменения его перед выходом. Как фильтр "the_content", который позволяет вам получить доступ к разметке для сообщения перед его выходом на экран.

Я пытаюсь найти фильтр catch-all, который дает мне последнюю трещину при модификации окончательной разметки целиком до вывода. Кто-нибудь знает об одном?

Я просматривал список фильтров несколько раз, но ничего не выпрыгивает на меня: http://adambrown.info/p/wp_hooks/hook/filters

(Я применил некоторые сообщества Wordpress для этого вопроса, но, не получив ни одного ответа, подумал, что я обращусь к почтенному SO.)

Теги:

7 ответов

14
Лучший ответ

AFAIK, для этого нет никакого крючка, поскольку темы используют HTML, который не будет обрабатываться WordPress.

Вы можете, однако, использовать буферизацию вывода, чтобы поймать окончательный HTML:

<?php
// example from php.net
function callback($buffer) {
  // replace all the apples with oranges
  return (str_replace("apples", "oranges", $buffer));
}
ob_start("callback");
?>
<html><body>
<p>It like comparing apples to oranges.</p>
</body></html>
<?php ob_end_flush(); ?>
/* output:
   <html><body>
   <p>It like comparing oranges to oranges.</p>
   </body></html>
*/
  • 2
    Вы можете использовать php register_shutdown_function, чтобы завершить буферизацию и получить html.
  • 0
    Это имеет один недостаток: вы не можете вызывать ob_start, ob_clean, .. внутри обратного вызова, что необходимо для определенной логики кэширования. php.net/manual/en/...
35

WordPress не имеет фильтра "окончательного вывода", но вы можете взломать его. Ниже приведен пример "Must Use" плагин, который я создал для проекта.

Примечание. Я не тестировал никаких плагинов, которые могли бы использовать действие "shutdown".

Плагин работает, повторяя все уровни открытых буферов, закрывая их и фиксируя их вывод. Затем он отключает фильтр "final_output", эхо отфильтрованное содержимое.

К сожалению, WordPress выполняет почти тот же самый процесс (закрытие открытых буферов), но фактически не захватывает буфер для фильтрации (просто сбрасывает его), поэтому дополнительные действия "shutdown" не будут иметь к нему доступа. Из-за этого ниже действие приоритизировано выше WordPress.

WP-содержание/мю-плагинов/buffer.php

<?php

/**
 * Output Buffering
 *
 * Buffers the entire WP process, capturing the final output for manipulation.
 */

ob_start();

add_action('shutdown', function() {
    $final = '';

    // We'll need to get the number of ob levels we're in, so that we can iterate over each, collecting
    // that buffer output into the final output.
    $levels = ob_get_level();

    for ($i = 0; $i < $levels; $i++) {
        $final .= ob_get_clean();
    }

    // Apply any filters to the final output
    echo apply_filters('final_output', $final);
}, 0);

Пример подключения к фильтру final_output:

<?php

add_filter('final_output', function($output) {
    return str_replace('foo', 'bar', $output);
});
  • 1
    Примечание. Я проверял это только в версии 3.8.
  • 1
    Спасибо большое, это самое элегантное решение.
Показать ещё 12 комментариев
18

вопрос может быть старым, но я нашел лучший способ сделать это.

function callback($buffer) {
  // modify buffer here, and then return the updated code
  return $buffer;
}

function buffer_start() { ob_start("callback"); }

function buffer_end() { ob_end_flush(); }

add_action('wp_head', 'buffer_start');
add_action('wp_footer', 'buffer_end');

Объяснение Этот код плагина регистрирует два действия - buffer_start и buffer_end.

buffer_start выполняется в конце раздела заголовка html. Параметр, функция callback, вызывается в конце буферизации вывода. Это происходит на нижнем колонтитуле страницы, когда выполняется второе зарегистрированное действие buffer_end.

Функция callback - это место, где вы добавляете свой код для изменения значения вывода (переменная $buffer). Затем вы просто возвращаете измененный код, и страница будет отображаться.

Примечания Обязательно используйте уникальные имена функций для buffer_start, buffer_end и callback, поэтому они не конфликтуют с другими функциями, которые могут быть у вас в плагинах.

  • 1
    Вы можете buffer_start_so_772510 префикс или суффикс своих примеров: buffer_start_so_772510 или so_772510_callback (я предпочитаю использовать суффикс, так как его легче читать). Таким образом, когда код появляется где-то еще, мы знаем, откуда он взялся;)
  • 0
    это не работает, когда вещи, которые вы хотите изменить или удалить, существуют после элемента нижнего колонтитула
Показать ещё 2 комментария
7

@jacer, если вы используете следующие перехватчики, заголовок также включается.

function callback($buffer) {      
    $buffer = str_replace('replacing','width',$buffer);
    return $buffer; 
}

function buffer_start() { ob_start("callback"); } 
function buffer_end() { ob_end_flush(); }

add_action('after_setup_theme', 'buffer_start');
add_action('shutdown', 'buffer_end');
  • 1
    Старайтесь не делать пост, который ссылается на другой ответ (и требует прочтения другого ответа, чтобы получить контекст); чем более разрозненным будет ваш ответ от ответа, на который вы ссылаетесь, тем труднее понять, что вы говорите. Кроме того, не обязательно плохо публиковать ответ, который строится на основе других, до тех пор, пока вы отдаете должное кредитам.
  • 2
    http://www.dagondesign.com/articles/wordpress-hook-for-entire-page-using-output-buffering/ - это ссылка, с которой был скопирован этот ответ.
3

Вы можете попробовать найти файл wp-includes/formatting.php. Например, функция wpautop. Если вы ищете что-то со всей страницей, посмотрите на плагин Super Cache. Это записывает окончательную веб-страницу в файл для кэширования. Увидев, как эти плагины могут дать вам некоторые идеи.

2

В последнее время в списке рассылки WP-Hackers появилась дискуссия о теме полной модификации страницы, и, похоже, консенсус заключался в том, что буферизация вывода с помощью ob_start() и т.д. была единственным реальным решением. Также обсуждались проблемы и недостатки: http://groups.google.com/group/wp-hackers/browse_thread/thread/e1a6f4b29169209a#

Подводя итог: он работает и является лучшим решением при необходимости (например, в плагине WP-Supercache), но замедляет общие скорости, потому что ваш контент не может быть отправлен в браузер как готовый, но вместо этого он должен дождаться полного документа, который будет отображаться (для ob_end()), прежде чем он может быть обработан вами и отправлен в браузер.

1

У меня возникли проблемы с этим кодом, так как я получаю исходный исходный код страницы, чтобы некоторые плагины не влияли на страницу. Я пытаюсь решить это сейчас - я havnt нашел много информации о лучших методах сбора данных из wordpress.

Обновление и разрешение:

Код из KFRIEND не работал у меня, так как это захватывает необработанный источник из wordpress, а не тот же вывод, который заканчивается в браузере infact. Мое решение, вероятно, не изящно, используя переменную globals для буферизации содержимого, но, по крайней мере, я знаю, что получается тот же собранный HTML-код, который доставляется в браузер. Возможно, что разные настройки плагинов создают проблемы, но благодаря примеру кода Jacer Omri выше я закончил с этим.

Этот код в моем случае находится, как правило, в functions.php в папке темы.

$GLOBALS['oldschool_buffer_variable'] = '';
function sc_callback($data){
    $GLOBALS['final_html'] .= $data;
    return $data;
}
function sc_buffer_start(){
    ob_start('sc_callback');
}
function sc_buffer_end(){
    // Nothing makes a difference in my setup here, ob_get_flush() ob_end_clean() or whatever
    // function I try - nothing happends they all result in empty string. Strange since the
    // different functions supposedly have very different behaviours. Im guessing there are 
    // buffering all over the place from different plugins and such - which makes it so 
    // unpredictable. But that why we can do it oldschool :D
    ob_end_flush();

    // Your final HTML is here, Yeeha!
    $output = $GLOBALS['oldschool_buffer_variable'];
}
add_action('wp_loaded', 'sc_buffer_start');
add_action('shutdown', 'sc_buffer_end');

Ещё вопросы

Сообщество Overcoder
Наверх
Меню