I have a custom post type ‘properties’ that I’d like to control the HTML output for. For simplicity, let’s focus on the archive view.
As a basic example, here is what a loop looks like in an archive.php
file:
<?php while ( have_posts() ) : the_post(); ?>
<h2><?php the_title(); ?></h2>
<div><?php the_content(); ?></div>
<?php endwhile; ?>
I’d like to be able to modify the output of the loop with my custom ‘properties’ HTML without adding a new template or using a shortcode – basically, without user intervention. Just to be clear, I’d like to replace the <h2>
and <div>
in the above example, and nothing before/after it.
Note: The above is only an example. I would like to control the loop output regardless of theme.
Right now I am using output buffering to capture the output from loop_start
to loop_end
and replacing it with my own, but this potentially can create conflicts with other plugins.
Is there an accepted/better way to do this?
There’re two very often forgotten action ref arrays: loop_start/_end()
.
Just turn on output buffering and you’re ready to go.
add_action( 'loop_start', 'wpse75307_plugin_loop' );
add_action( 'loop_end', 'wpse75307_plugin_loop' );
/**
* Callback function triggered during:
* + 'loop_start'/`have_posts()` after the last post gets rendered
* + 'loop_end'/`the_post()` before the 1st post gets rendered
* @param object \WP_Query Passed by reference
* @return
*/
function wpse75307_plugin_loop( &$obj )
{
# if ( is_main_query() )
# DO STUFF ... OR DONT
global $post;
// Start output buffering at the beginning of the loop and abort
if ( 'loop_start' === current_filter() )
return ob_start();
// At the end of the loop, we end the buffering and save into a var
# if ( is_main_query() )
# DO STUFF ... OR DONT
$loop_content = ob_get_flush();
// You can do something with $loop_content...
// Add your own loop, or...
// Whatever you can imagine
}
Note: I wouldn’t do it like this, but as you said, you want exactly that level of overriding, here you go.