用于修改最终 html 输出的 WordPress 过滤器
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/772510/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
WordPress filter to modify final html output
提问by ryonlife
WordPress has great filter support for getting at all sorts of specific bits of content and modifying it before output. Like the_content
filter, which lets you access the markup for a post before it's output to the screen.
WordPress 具有强大的过滤器支持,可以获取各种特定的内容并在输出之前对其进行修改。就像the_content
过滤器一样,它允许您在将帖子输出到屏幕之前访问它的标记。
I'm trying to find a catch-all filter that gives me one last crack at modifying the final markup in its entirety before output.
我试图找到一个包罗万象的过滤器,它让我在输出之前完全修改最终标记时最后一次破解。
I've browsed the list of filters a number of times, but nothing jumps out at me: https://codex.wordpress.org/Plugin_API/Filter_Reference
我已多次浏览过滤器列表,但没有任何内容让我感到惊讶:https: //codex.wordpress.org/Plugin_API/Filter_Reference
Anyone know of one?
有人知道吗?
采纳答案by moff
AFAIK, there is no hook for this, since the themes uses HTML which won't be processed by WordPress.
AFAIK,这没有钩子,因为主题使用 WordPress 不会处理的 HTML。
You could, however, use output bufferingto catch the final 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>
*/
回答by kfriend
WordPress doesn't have a "final output" filter, but you can hack together one. The below example resides within a "Must Use"plugin I've created for a project.
WordPress 没有“最终输出”过滤器,但您可以组合一个。下面的示例位于我为项目创建的“必须使用”插件中。
Note: I haven't tested with any plugins that might make use of the "shutdown" action.
注意:我没有测试任何可能使用“关闭”操作的插件。
The plugin works by iterating through all the open buffer levels, closing them and capturing their output. It then fires off the "final_output" filter, echoing the filtered content.
该插件通过迭代所有打开的缓冲区级别,关闭它们并捕获它们的输出来工作。然后它触发“final_output”过滤器,回应过滤后的内容。
Sadly, WordPress performs almost the exact same process (closing the open buffers), but doesn't actually capture the buffer for filtering (just flushes it), so additional "shutdown" actions won't have access to it. Because of this, the below action is prioritized above WordPress's.
可悲的是,WordPress 执行几乎完全相同的过程(关闭打开的缓冲区),但实际上并没有捕获缓冲区进行过滤(只是刷新它),因此额外的“关闭”操作将无法访问它。因此,以下操作的优先级高于 WordPress。
wp-content/mu-plugins/buffer.php
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);
An example of hooking into the final_output filter:
挂钩到 final_output 过滤器的示例:
<?php
add_filter('final_output', function($output) {
return str_replace('foo', 'bar', $output);
});
Edit:
编辑:
This code uses anonymous functions, which are only supported in PHP 5.3 or newer. If you're running a website using PHP 5.2 or older, you're doing yourself a disservice. PHP 5.2 was released in 2006, and even though Wordpress (edit: in WP version < 5.2) STILL supports it, you should not use it.
此代码使用匿名函数,仅在 PHP 5.3 或更高版本中支持。如果您使用 PHP 5.2 或更早版本运行网站,那么您就是在伤害自己。PHP 5.2 于 2006 年发布,即使 Wordpress(编辑:在 WP 版本 < 5.2 中)仍然支持它,您也不应该使用它。
回答by Jacer Omri
The question is may be old, but I have found a better way to do it:
问题可能很老,但我找到了更好的方法:
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');
ExplanationThis plugin code registers two actions – buffer_start
and buffer_end
.
说明此插件代码注册了两个操作 -buffer_start
和buffer_end
.
buffer_start
is executed at the end of the header section of the html. The parameter, the callback
function, is called at the end of the output buffering. This occurs at the footer of the page, when the second registered action, buffer_end
, executes.
buffer_start
在 html 的标题部分的末尾执行。callback
在输出缓冲结束时调用参数函数。这发生在页面的页脚,当第二个注册的动作buffer_end
执行时。
The callback
function is where you add your code to change the value of the output (the $buffer
variable). Then you simply return the modified code and the page will be displayed.
该callback
函数是您添加代码以更改输出值($buffer
变量)的地方。然后您只需返回修改后的代码,页面就会显示出来。
NotesBe sure to use unique function names for buffer_start
, buffer_end
, and callback
, so they do not conflict with other functions you may have in plugins.
注意确保为buffer_start
、buffer_end
和使用唯一的函数名称callback
,这样它们就不会与插件中可能具有的其他函数发生冲突。
回答by Nick Kuijpers
@jacer, if you use the following hooks, the header.php also gets included.
@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');
回答by Arne L
I was using the top solution of this post (by kfriend) for a while. It uses an mu-plugin
to buffer the whole output.
我使用了这篇文章的顶级解决方案(由 kfriend)有一段时间了。它使用 anmu-plugin
来缓冲整个输出。
But this solution breaks the caching of wp-super-cache
and no supercache-files are generated when i upload the mu-plugin
.
但是这个解决方案破坏了缓存,wp-super-cache
并且当我上传mu-plugin
.
So: If you are using wp-super-cache
, you can use the filter of this plugin like this:
所以:如果你正在使用wp-super-cache
,你可以像这样使用这个插件的过滤器:
add_filter('wp_cache_ob_callback_filter', function($buffer) {
$buffer = str_replace('foo', 'bar', $buffer);
return $buffer;
});
回答by okto
Modified https://stackoverflow.com/users/419673/kfriendanswer.
修改了https://stackoverflow.com/users/419673/kfriend答案。
All code will be on functions.php. You can do whatever you want with the html on the "final_output" filter.
所有代码都在functions.php 上。您可以对“final_output”过滤器上的 html 做任何您想做的事情。
On your theme's 'functions.php'
在您主题的“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);
});
回答by Brent Baisley
You might try looking in the wp-includes/formatting.php file. For example, the wpautop function. If you are looking for doing something with the entire page, look at the Super Cache plugin. That writes the final web page to a file for caching. Seeing how that plug-in works may give you some ideas.
您可以尝试查看 wp-includes/formatting.php 文件。例如,wpautop 函数。如果您正在寻找对整个页面执行某些操作,请查看 Super Cache 插件。这会将最终网页写入文件以进行缓存。查看该插件的工作原理可能会给您一些想法。
回答by Brent Baisley
Indeed there was a discusussion recently on the WP-Hackers mailing list about the topic of full page modification and it seems the consensus was that output buffering with ob_start() etc was the only real solution. There was also some discussion about the upsides and downsides of it: http://groups.google.com/group/wp-hackers/browse_thread/thread/e1a6f4b29169209a#
事实上,最近在 WP-Hackers 邮件列表上有一个关于整页修改主题的讨论,似乎共识是使用 ob_start() 等进行输出缓冲是唯一真正的解决方案。还有一些关于它的优点和缺点的讨论:http: //groups.google.com/group/wp-hackers/browse_thread/thread/e1a6f4b29169209a#
To summarize: It works and is the best solution when necessary (like in the WP-Supercache plugin) but slows down overall speeds because your content isn't allowed to be sent to the browser as its ready, but instead has to wait for the full document to be rendered (for ob_end() ) before it can be processed by you and sent to the browser.
总结:它可以工作并且是必要时的最佳解决方案(如在 WP-Supercache 插件中)但会降低整体速度,因为您的内容不允许在准备就绪时发送到浏览器,而是必须等待在您可以处理并发送到浏览器之前,要呈现完整的文档(对于 ob_end() )。
回答by Kim Steinhaug
I have run into problems with this code, as I end up with what seems to be the original source for the page so that some plugins has no effect on the page. I am trying to solve this now - I haven't found much info regarding best practises for collecting the output from WordPress.
我遇到了这段代码的问题,因为我最终得到的似乎是页面的原始来源,因此某些插件对页面没有影响。我现在正在尝试解决这个问题 - 我没有找到太多关于从 WordPress 收集输出的最佳实践的信息。
Update and solution:
更新和解决方案:
The code from KFRIEND didnt work for me as this captures unprocessed source from WordPress, not the same output that ends up in the browser in fact. My solution is probably not elegant using a globals variable to buffer up the contents - but at least I know get the same collected HTML as is delivered to the browser. Could be that different setups of plugins creates problems but thanks to code example by Jacer Omri above I ended up with this.
KFRIEND 的代码对我不起作用,因为它捕获了来自 WordPress 的未处理源,实际上与浏览器中的输出不同。我的解决方案可能不是使用全局变量来缓冲内容的优雅 - 但至少我知道获得与传递给浏览器相同的收集的 HTML。可能是插件的不同设置会产生问题,但由于上面 Jacer Omri 的代码示例,我最终得到了这个。
This code is in my case located typically in functions.php in theme folder.
在我的情况下,此代码通常位于主题文件夹中的 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');
回答by Lucas Bustamante
Try to solve it with JavaScript first before using output buffers.
在使用输出缓冲区之前,先尝试用 JavaScript 解决它。
Let's say you want to add a spinner while loading iframes, for example:
假设您想在加载 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);
Adapt that idea to your needs, usually you should be able to manipulate HTML output with JavaScript without the need to mess with output buffers, that can break cache, for instance.
根据您的需要调整这个想法,通常您应该能够使用 JavaScript 操作 HTML 输出,而无需弄乱输出缓冲区,例如,这可能会破坏缓存。