I am utilizing a template-type system, to filter the_content
. My filter contains this partial code:
ob_start();
include_once ( self::$dir . 'views/templates/' . $post_type . '/' . $display . '.php' );
$contents = ob_get_clean();
return $contents;
For some reason, this works locally but not a test server (WP Engine – nginx). I have verified that the file is indeed being included.
On the test server, $contents
is actually an empty string (I var_dump’ed it to be sure, it’s string(0)""
).
What is bizarre is that I replaced the above code with:
ob_start();
include_once ( self::$dir . 'views/templates/' . $post_type . '/' . $display . '.php' );
ob_flush_clean();
just for fun. This code outputs the object buffered template page to the screen. I cannot use ob_flush because I need to return the object buffer. Outputting the buffer causes it to display in the wrong place, obviously because I need to return the string from the filter.
Why does ob_get_clean()
return an empty string while ob_end_flush()
outputs the correct buffer content to the page?
After some thinking, I switched the include_once
to plain ‘ol include
.
This had the effect of causing the server to generate a 502 error.
So…I’m now thinking that for some reason my filter is causing some type of loop or something be being called multiple times? I’m honestly not sure. I researched what others in my situation have done, and my code looks practically identical to other methods of using a custom template system.
An important note: When the callback is called via a shortcode, it behaves as expected.
The whole point of this is using custom meta data/page content layout for single & archive displays of CPT’s in a theme-independent way. The shortcode is used for the archive-type display (I say archive-type because it’s a manually induced archive, not a typical archive-{cpt}.php). I went with a shortcode for the ‘archive’ pages so that the site owner could have control over the permalink, title, and overall content of the archive page. I went with a filter on the_content
so it can be theme-independent as possible.
Full filter code:
add_filter( 'the_content', array( $this, 'filter_content' ) );
function filter_content($content) {
global $post;
if( !$this->we_belong_here() ) {
//does post type check
return $content;
}
$display = 'archive';
if( is_single( $post ) ) {
$display = 'single';
}
return $this->shortcode( array( 'post_type' => $post->post_type, 'display' => $display, 'content' => $content, 'method' => 'class' ) );
}
function shortcode($atts) {
extract( shortcode_atts( array(
'post_type' => '',
'display' => 'archive',
'method' => 'shortcode',
'content' => ''
), $atts ) );
ob_start();
include ( self::$dir . 'views/templates/' . $post_type . '/' . $display .'.php' );
$contents = ob_get_clean();
if($contents) return $contents; else return $content;
}
The reason my code was failing was due to it reaching a memory limit.
I was adding a filter to the_content, and was calling another plugin’s API (Custom Field Suite) to get some meta data that was of the WYSIWYG type. This type of field runs through the_content filter, so I was hitting an infinite loop.
I couldn’t find this out on WP Engine because they have very limited error logging.
I ended up testing the site on a MediaTemple server, which resulted in the correct error message being displayed.
To fix this, I removed the filter from the_content BEFORE I called the meta data getter, then added it back after.