Add function after the_content
-
26-04-2021 - |
Question
I have the following function within a simple plugin:
<?php
/**
* Social buttons
*/
function zss_social_buttons() {
?>
<div class="zss">
<!-- Facebook -->
<div id="fb-root"></div>
<script>
(function(d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) return;
js = d.createElement(s); js.id = id;
js.src = "https://connect.facebook.net/en_US/sdk.js#xfbml=1&version=v3.0";
fjs.parentNode.insertBefore(js, fjs);
}
(document, 'script', 'facebook-jssdk'));
</script>
<div class="fb-share-button" data-href="<?php the_permalink(); ?>" data-layout="button_count" data-lazy="true">
</div>
<!-- Twitter -->
<a href="https://twitter.com/share?url=<?php the_permalink(); ?>&text=<?php echo urlencode( get_the_title() ); ?>" title="Share on Twitter" target="_blank" rel="nofollow noopener noreferrer" class="zss-button zss-button--twitter">Twitter</a>
<!-- LinkedIn -->
<a class="zss-button zss-button--linkedin" href="http://www.linkedin.com/shareArticle?mini=true&url=<?php the_permalink(); ?>" title="Share on LinkedIn" target="_blank" rel="nofollow noopener noreferrer">LinkedIn</a>
<!-- E-Mail -->
<a class="zss-button zss-button--email" href="mailto:?subject=<?php the_title(); ?>&body=<?php the_permalink(); ?>" title="Share by Email" target="_blank" rel="noopener">Email</a>
</div>
<?php }
I'd like my social share buttons to appear underneath the_content()
via each single post. To achieve this, I've built the following filter hook in the same plugin:
<?php
/**
* Insert share button
*/
function zss_insert_share_buttons( $content ) {
if ( is_singular() && in_the_loop() && is_main_query() ) {
$social_share_buttons = zss_social_buttons();
$content .= $social_share_buttons;
return $content;
}
else {
return $content;
}
}
add_filter( 'the_content', 'zss_insert_share_buttons' );
For some reason, the zss_social_buttons()
function loads before the_content();
. What have I done wrong here?
Solution
The main issue in your code is caused by the call to zss_social_buttons()
in your filter function:
// In zss_insert_share_buttons():
$social_share_buttons = zss_social_buttons(); // NULL
$content .= $social_share_buttons;
And the problem there is that zss_social_buttons()
is echoing the sharing links/buttons instead of returning them, so they're not actually added to the $content
variable. Instead, they're sent to the browser (or displayed) immediately when the function runs.
So that explains why the buttons appear before the post content. ( That's what you meant by "the zss_social_buttons()
function loads before the_content();
", right? )
Additionally, the Facebook script and including the <div id="fb-root"></div>
should be added only once and not every time the filter the_content
is applied. So for example, you can use the wp_body_open
(action) hook to add the script right after the <body>
tag:
add_action( 'wp_body_open', 'my_wp_body_open' );
function my_wp_body_open() {
?>
<!-- Load Facebook SDK for JavaScript -->
<div id="fb-root"></div>
<script>put the script code here</script>
<?php
}
And then, to fix the main issue, you can either:
Make the
zss_social_buttons()
function returns the output and not echoing it. Simplified example:<?php function zss_social_buttons() { return '<div class="zss"> <!-- Facebook --> <div class="fb-share-button" data-href="' . esc_url( get_the_permalink() ) . '"' . ' data-layout="button_count" data-lazy="true"></div> ... your other buttons. </div>'; }
Or you can use output buffering in the
zss_insert_share_buttons()
function:<?php function zss_social_buttons() { ?> <div class="zss"> <!-- Facebook --> <div class="fb-share-button" data-href="<?php the_permalink(); ?>" data-layout="button_count" data-lazy="true"></div> ... your other buttons. </div> <?php } function zss_insert_share_buttons( $content ) { if ( is_singular() && in_the_loop() && is_main_query() ) { ob_start(); zss_social_buttons(); // echo the output, but send it to the buffer and // not the browser $content .= ob_get_clean(); // and then append the buffer to $content } return $content; }