WordPress具有出色的过滤器支持,可以获取各种特定内容并在输出之前对其进行修改。就像“the_content”过滤器一样,它允许您在帖子输出到屏幕之前访问帖子的标记。
我正在尝试找到一个全能的过滤器,它让我在输出之前完成修改最终标记的最后一次破解。有人知道吗?
我已多次浏览过滤器列表,但没有任何内容突然出现在我面前: http://adambrown.info/p/wp_hooks/hook/filters
(我已经针对这个问题点了一些特定于WordPress的社区,但没有收到一个回复,我以为我会转向那个值得尊敬的SO。)
答案 0 :(得分:50)
WordPress没有"最终输出"过滤器,但你可以一起破解。以下示例位于我为项目创建的"Must Use"插件中。
注意:我没有使用任何可能使用" shutdown"的插件进行测试。动作。
插件通过迭代所有打开的缓冲区级别,关闭它们并捕获它们的输出来工作。然后它会触发" final_output"过滤,回显过滤后的内容。
可悲的是,WordPress执行几乎完全相同的过程(关闭打开的缓冲区),但实际上并没有捕获缓冲区进行过滤(只是刷新它),所以额外的"关闭"动作无法访问它。因此,以下操作优先于WordPress。
可湿性粉剂内容/亩-插件/ 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或更早版本运行网站,那么您自己就是一种伤害。 PHP 5.2于2006年发布,即使Wordpress(编辑:在WP版本&lt; 5.2 中)STILL支持它,也不应该使用它。
答案 1 :(得分:19)
这个问题可能很旧,但我找到了一个更好的方法。
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
的唯一函数名称,这样它们就不会与插件中的其他函数冲突。
答案 2 :(得分:18)
AFAIK,没有这方面的钩子,因为主题使用的是WordPress不会处理的HTML。
然而,你可以use output buffering来捕捉最终的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>
*/
答案 3 :(得分:13)
@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');
答案 4 :(得分:3)
您可以尝试查看wp-includes / formatting.php文件。例如,wpautop函数。 如果您正在寻找整个页面的内容,请查看Super Cache插件。这会将最终的网页写入文件以进行缓存。看看该插件的工作原理可能会给你一些想法。
答案 5 :(得分:3)
最近WP-Hackers邮件列表上有关于整页修改主题的讨论,似乎共识是使用ob_start()等输出缓冲是唯一真正的解决方案。还讨论了它的优点和缺点:http://groups.google.com/group/wp-hackers/browse_thread/thread/e1a6f4b29169209a#
总结一下:它是有效的,并且是必要时的最佳解决方案(例如在WP-Supercache插件中),但会降低整体速度,因为您的内容不允许在准备好时发送到浏览器,而是必须等待完整文档呈现(对于ob_end()),然后由您处理并发送到浏览器。
答案 6 :(得分:2)
一段时间以来,我一直在使用此帖子的最佳解决方案(由kfriend进行)。它使用X = [[[X1, X2, X3],[X1, X4, X5, X6]],
[[0],[X3, X4]]]
Y = [[[Y1, Y2, Y3, Y4],[0]],
[[Y4, Y5, Y6],[Y1]]]
缓冲整个输出。
但是此解决方案中断了mu-plugin
的缓存,并且在我上载wp-super-cache
时没有生成任何超级缓存文件。
因此:如果您使用的是mu-plugin
,则可以使用此插件的过滤器,如下所示:
wp-super-cache
答案 7 :(得分:2)
修改后的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);
});
答案 8 :(得分:1)
我遇到了这段代码的问题,因为我最终看起来似乎是页面的原始来源,所以一些插件对页面没有影响。我现在正试图解决这个问题 - 我没有找到有关从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');
答案 9 :(得分:1)
为了简化之前的答案,只需在 functions.php
中使用它:
ob_start();
add_action('shutdown', function () {
$html = ob_get_clean();
// ... modify $html here
echo $html;
}, 0);
答案 10 :(得分:0)
在使用输出缓冲区之前,请先尝试使用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输出,而无需弄乱可能会破坏缓存的输出缓冲区。