I have been working my way around this one for a few months now, never bothering to think about the best solution. There is not, in fact, a WordPress simple function to get the excerpt outside of the WordPress loop. Why would you want to do that you ask…
Example:
I have a plugin I have written to create a basic shopping cart and shop front. It makes use of a simple shortcode on a Page to generate the shop which is based on a custom post type called Products. The Loop is used on the main page itself to generate the WordPress Page and subsequently process the shortcode. I loop through the products using a query_posts statement to bung the data into an array (for caching and manipulating so using a child Loop isn’t possible here) and then loop over it again later on. I want to show the Excerpt (which may or may not exist) on the shop front and the full description for my individual product pages.
So I initially thought of doing something like the following:
<?php
$product = get_page($product_id);
echo $product->post_excerpt;
?>
What this approach does wrong is returns nothing at all when the user hasn’t filled in an Excerpt for the product they entered. WordPress normally takes a selection of text from the main content, strips out any HTML and shortcodes and shows that instead.
Next option is this:
<?php
echo get_the_excerpt();
?>
What this does is prints the excerpt for the page which the shop front it hosted on (the parent page) because, as far as The Loop is concerned, the context of the page isn’t a shop front, it’s just a normal Page.
So why does this not work?
<?php
echo get_the_excerpt($product_id);
?>
Well some bright spark on a blog out in the ether thought it did however, regardless of what the argument for the function was initially, it no longer works as has been depracated (the argument that is).
So what’s the solution… well sadly it’s a custom function of your own. Luckily for you I have backtraced the code and writted my own little version of the above and it works a treat…
<?php
function get_the_excerpt($id=false) {
global $post;
$old_post = $post;
if ($id != $post->ID) {
$post = get_page($id);
}
if (!$excerpt = trim($post->post_excerpt)) {
$excerpt = $post->post_content;
$excerpt = strip_shortcodes( $excerpt );
$excerpt = apply_filters('the_content', $excerpt);
$excerpt = str_replace(']]>', ']]>', $excerpt);
$excerpt = strip_tags($excerpt);
$excerpt_length = apply_filters('excerpt_length', 55);
$excerpt_more = apply_filters('excerpt_more', ' ' . '[...]');
$words = preg_split("/[\n\r\t ]+/", $excerpt, $excerpt_length + 1, PREG_SPLIT_NO_EMPTY);
if ( count($words) > $excerpt_length ) {
array_pop($words);
$excerpt = implode(' ', $words);
$excerpt = $excerpt . $excerpt_more;
} else {
$excerpt = implode(' ', $words);
}
}
$post = $old_post;
return $excerpt;
}
?>
I have put mine in a class I used for my plugins these days as a helper function however just rename it (to avoid a naming conflict with it’s namesake) and call it from your plugin or theme as you would normally.
hope this helps someone out. Please let me know if anyone knows a better or simpler way. This works for me but I really wish there wasn’t such a monumental oversight by the WordPress guys on this one (other than creating sub loops which just feels wrong and inflexible to me)