web-dev-qa-db-ja.com

WordPress最終的なHTML出力を変更するフィルター

WordPressには、あらゆる種類の特定のコンテンツを取得して出力前に変更するための優れたフィルターサポートがあります。 「the_content」フィルターと同様に、画面に出力する前に投稿のマークアップにアクセスできます。

出力前に最終的なマークアップ全体を変更する際に最後の亀裂を与えるキャッチオールフィルターを見つけようとしています。誰でも知っていますか?

フィルターのリストを何度も参照しましたが、何も飛び出しません。 http://adambrown.info/p/wp_hooks/hook/filters

(私はこの質問のためにいくつかのWordPress固有のコミュニティをタップしましたが、1つの返信を受け取っていませんでした。

51

私の知る限り、テーマにはWordPressで処理されないHTMLが使用されているため、これに対するフックはありません。

ただし、 出力バッファリングを使用 で最終的な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's like comparing apples to oranges.</p>
</body></html>
<?php ob_end_flush(); ?>
/* output:
   <html><body>
   <p>It's like comparing oranges to oranges.</p>
   </body></html>
*/
20
moff

WordPressには「最終出力」フィルターはありませんが、一緒にハックできます。以下の例は、プロジェクト用に作成した "Must Use" プラグイン内にあります。

注:「シャットダウン」アクションを使用する可能性のあるプラグインではテストしていません。

プラグインは、開いているすべてのバッファレベルを繰り返し処理し、閉じて出力をキャプチャします。次に、「final_output」フィルターを起動し、フィルター処理されたコンテンツをエコーし​​ます。

悲しいことに、WordPressはほぼ同じプロセス(オープンバッファを閉じる)を実行しますが、実際にはフィルタリングのためにバッファをキャプチャしない(フラッシュするだけ)ので、追加の "シャットダウン"アクションは実行されません。このため、以下のアクションはWordPressよりも優先されます。

wp-content/mu-plugins/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's 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);
});

編集:

このコードは、PHP 5.3以降でのみサポートされている匿名関数を使用します。PHP 5.2以前を使用してWebサイトを実行している場合、 PHP 5.2は2006年にリリースされましたが、Wordpress(edit:in WP version <5.2)それでもサポートしています。使用しないでください。

53
kfriend

質問は古いかもしれませんが、より良い方法を見つけました。

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_startbuffer_endの2つのアクションを登録します。

buffer_startは、htmlのヘッダーセクションの最後で実行されます。パラメータ、callback関数は、出力バッファリングの最後に呼び出されます。これは、2番目に登録されたアクションbuffer_endが実行されるときに、ページのフッターで発生します。

callback関数は、コードを追加して出力の値($buffer変数)を変更する場所です。次に、変更したコードを返すだけで、ページが表示されます。

buffer_startbuffer_end、およびcallbackには必ず一意の関数名を使用してください。そうすれば、プラグインにある他の関数と競合しません。

19
Jacer Omri

@jacer、次のフックを使用すると、header.phpも含まれます。

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');
13
Nick Kuijpers

Wp-includes/formatting.phpファイルを調べてみてください。たとえば、wpautop関数。ページ全体で何かをしたい場合は、スーパーキャッシュプラグインをご覧ください。これにより、最終的なWebページがキャッシュ用のファイルに書き込まれます。そのプラグインがどのように機能するかを見ると、いくつかのアイデアが得られます。

3
Brent Baisley

私はしばらくの間、この投稿の一番上のソリューション(kfriendによる)を使用していました。 mu-pluginを使用して、出力全体をバッファリングします。

しかし、このソリューションはwp-super-cacheのキャッシュを壊し、mu-pluginをアップロードするときにスーパーキャッシュファイルが生成されません。

したがって:wp-super-cacheを使用している場合は、このプラグインのフィルターを次のように使用できます。

add_filter('wp_cache_ob_callback_filter', function($buffer) {
    $buffer = str_replace('foo', 'bar', $buffer);
    return $buffer;
});
2
Arne L

変更 https://stackoverflow.com/users/419673/kfriend 回答。

すべてのコードはfunctions.phpにあります。 「final_output」フィルターのhtmlを使用して、必要な処理を実行できます。

テーマの「functions.php」

//we use 'init' action to use ob_start()
add_action( 'init', 'process_post' );

function process_post() {
     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's 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);

add_filter('final_output', function($output) {
    //this is where changes should be made
    return str_replace('foo', 'bar', $output); 
});
2
okto

一部のプラグインがページに影響を与えないように、ページの元のソースと思われるものになるため、このコードで問題が発生しました。私は今これを解決しようとしています-WordPressからの出力を収集するためのベストプラクティスに関する多くの情報が見つかりません。

更新と解決策:

KFRIENDのコードは、実際にはブラウザーに出力されるのと同じ出力ではなく、WordPressから未処理のソースをキャプチャするため、機能しませんでした。私の解決策はおそらく、グローバル変数を使用してコンテンツをバッファリングするエレガントではありません-少なくとも、ブラウザに配信されたものと同じ収集された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 happens 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's why we can do it old school :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');
1
Kim Steinhaug

出力バッファーを使用する前に、まずJavaScriptで解決してください。

たとえば、iframeの読み込み中にスピナーを追加するとします。

(function ($) {

    $(document).ready(function () {
        showSpinnerWhileIFrameLoads();
    });

    function showSpinnerWhileIFrameLoads() {
        var iframe = $('iframe');
        if (iframe.length) {
            $(iframe).before('<div id=\'spinner\'><i class=\'fa fa-spinner fa-spin fa-3x fa-fw\'></i></div>');
            $(iframe).on('load', function() {
                document.getElementById('spinner').style.display='none';
            });
        }
    }

})(jQuery);

その考えをニーズに合わせて調整してください。通常、たとえばキャッシュを壊す可能性がある出力バッファを台無しにすることなく、JavaScriptでHTML出力を操作できるはずです。

0