Shortcode for Includes
One thing that WordPress doesn’t have the ability to do “out-of-the-box” is do includes, in the sense of including the content of one post into the content of another post directly in the post editor. For the umpteenth time around here, shortcodes to the rescue!
This issue came up while my co-worker Tim at Wufoo was documenting parts of the latest Wufoo API. Some of the API pages have areas on them that are exactly the same as other pages. For example, we were finding entire chunks of navigation that were linking to alternate pages of documentation.
One possible way to deal with this is to make a special template just for these pages and include that chunk inside that template. This solution edges on the issue of template-bloat which I’ve been thinking a lot about lately. Creating a new template every time you need one little change is solving the problem with a sledgehammer rather than a scalpel.
The ideal solution is just to make a shortcode. You pass the ID of the post (in our case, page) that you want to include and the shortcode is replaced with that content. This is the usage, where XXXX would be the ID of the post:
[digwp_include postidparam=XXXX]
To make it work, we’ll add a fairly simple function to the functions.php file in our theme. The function will take the parameter, run a query for it, and return back the content if it finds any:
function digwp_includeContentShortcode($atts) {
$thepostid = intval($atts[postidparam]);
$output = '';
query_posts("p=$thepostid&post_type=page");
if (have_posts()) : while (have_posts()) : the_post();
$output .= get_the_content($post->ID);
endwhile; else:
// failed, output nothing
endif;
wp_reset_query();
return $output;
}
// USAGE
// In the post content, you can use [digwp_include postidparam="1234"]
// "1234" would be the WordPress ID of the Page you are trying to include
add_shortcode("digwp_include", "digwp_includeContentShortcode");
Now you can publish small modules of content, and include them on any Post/Page that needs them! I’d probably create a Page on your site called like “Includes” or “Modules” and post them as Pages with that as the Parent Page. That way you don’t clutter up the root and they all stay organized together.
Check out this graphic, which hopefully will drive home the idea:
[ Click here for full-size view ]
Random notes
- This is similar to the custom loop shortcode I previously published.
- This may be good territory for a plugin rather than functions.php code.
- Notice the function is properly prefixed.
28 responses
-
query_posts()
should only be used for modifying the primary loop, not creating a secondary loop. get_posts() is what to use for that.Also that’s not how
get_the_content()
works (it’s first argument is the “more” text).Anyway, here’s the best code for this situation:
function digwp_includeContentShortcode( $atts ) { $thepostid = (int) $atts['postidparam']; if ( ! $post = get_post( $thepostid ) ) return '<em>Invalid post/page ID.</em>'; return apply_filters( 'the_content', $post->post_content ); }
-
You can also try this plugin. Nice because you can also use php code in order to include content in your template.
-
Seems this could come in handy for the 3.org Codex redesign ;-)
-
You may not want to do this exact thing if you’re concerned about the duplicate content SEO issues. How I’ve gotten around this, in a way that actually improves PageRank flow, is to have it grab the_excerpt or the custom description meta and display it and a link to the post. It’s better to not repeat yourself, in programming terms and in SEO terms.
I’d also second the notion that custom post types would be best for this, rather than “pages”.
Alex’s arguments and the confusion of the wp_query system by two popular and successful WP devs perfectly demonstrates why WP should have a more modular loop system where template tags can be scoped to a particular instance of a query, rather than the assumption that everything is the global post. I know I’m talking out of my level of PHP, but I, and most WP developers I know of, run into that issue all the time.
-
This is an interesting solution but seems to me it would be easier to add small snippets of code to a functions file and then call/place them into a post/page using a userfunction, like;
userfunc_snippetname0()
. I use runPHP plugin to allow PHP on posts/pages.Granted, you can’t change the content from within WordPress admin but it seems a cleaner option than having a slew of extra pages. But for lengthier content, the shortcode option is nice.
Thanks for sharing.
-
That comment got hosed; 1st paragraph should read:
This is an interesting solution but seems to me it would be easier to add small snippets of code to a functions file and then call/place them into a post/page using a userfunction, like:
userfunc_snippetname0()
-
i might use this one day.. bookmarked!
-
Here’s a goofy question. Why would this work if I preview the page. BUT, if I view the live version I get the following error:
This webpage has a redirect loop.
The webpage at
http://example.com/
has resulted in too many redirects. Clearing your cookies for this site or allowing third-party cookies may fix the problem. If not, it is possibly a server configuration issue and not a problem with your computer.Error 310 (net::ERR_TOO_MANY_REDIRECTS): There were too many redirects.
-
Hmm working now: I had already deleted the page and created a new page. SOLUTION:
Even though I permenantly deleted the old page, I had to give it a new name. So I have PAGE1 (source), then PAGE2 (show source content) deleted PAGE2. got the loop error. CREATED PAGE2-2 — WORKING.
-
Works like a dream, BUT and there’s always a but….
I have Custom Fields which I would like to put the shortcode include in but shortcodes don’t run in custom fields. Any code I can add to the function.php to get the custom fields to work with shortcodes?
I’m using Page.ly Multi-edit plugin to give the user a panel of content to update and some of these panels will just be includes of common content, but means with your solution they can still maintain that content. it’s this plugin that uses custom fields hence the need for the shortcodes to work.
Any guidance please ?
-
Could someone please assist me?? When I use the above, its grabbing the content. But it is not placing the html formatting around
<p>
tags etc like wordpress normally would. The original post has all the hard returns replaced with tags. However when I run this – it grabs all of the copy. But if there is no specific tag hardcoded – then all I get is one big run-on.-
hi Acts7, try to use:
$output .= apply_filters('the_content',get_the_content($post->ID));
that will put the ‘formatting’ back on.
-
Alchymyth – THANKS A LOT. I had just come across a similar solution and I found your reply.
return apply_filters( 'the_content', $post->post_content );
Could you tell me – what the difference is between
apply_filters( 'the_content', $post->post_content );
and
apply_filters('the_content',get_the_content($post->ID));
Are these two identical? Or is there a difference in what they are pulling?
-
Take a look at the source of
get_the_content()
. ;)get_the_content()
hides the content of password protected but also does some stuff with the “more” feature.Probably better to use
get_the_content()
. -
Thanks for clearing that up Alex
-
-
-
-
PLEASE PLEASE??? Someone explain this?
//$output .= get_the_content($post->ID);
$output .= the_content($post->ID);
I’ve searched. And when using “get_the_content” I get the raw content.
When I use “the_content” I get what I want – content that gets html formatted.What is the functional difference? And why would you ever want it to not maintain its html formatting? Is that the difference? AND Is it safe to use “the_content” rather than “get_the_content”?
-
Did anyone ever fix @Alex’s code? It doesn’t return just content, it includes the title.
-
I think you’re mistaken. My code doesn’t go anywhere near the title of the post.
-