views:

101

answers:

7

I have a function whos purpose is to return some HTML ($offer_html) to display on my page. However, I´m seeing some strange things.

Below you see a div is added first to $offer_html (DIV is closing at the end).

$offer_html = '<div class="box middle offer alignleft">';
$offer_html .= '<p class="detail alignleft">' . $volum . '</p>';
$offer_html .= '<p class="detail alignleft">' . $produsent . '</p>';
$offer_html .= wpfp_link();
$offer_html .= '</div';

return $offer_html;

My problem is with the function wpfp_link(). The function returns HTML, but this HTML ends up totally misplaced. When the page renders, the HTML looks like this:

<img class="wpfp-img" title="Favorite" alt="Favorite" src="http://localhost:8888/wordpress/wp-content/plugins/wp-favorite-posts/img/remove.png"&gt;
<div class="box middle offer alignleft">
</div>

As you see, the HTML returned by the wpfp_link() ends up outside the DIV which I want it to be inside.

Does anyone know why this happens?

+1  A: 

It's impossible to tell for sure from what little code you show, but maybe you need to directly echo the string instead of returning it.

Pekka
+3  A: 

You wpfp_link() does not return the HTML string, it directly echo's the string. You've to catch that from the output buffer like the following:

<?php
// Turn on outbut buffering
ob_start();


function your_function()
{
    // Fill outbut buffer
    wpfp_link();

    // Fetch and clean output buffer
    $wpfp_html = ob_get_clean();

    $offer_html = '<div class="box middle offer alignleft">';
    $offer_html .= '<p class="detail alignleft">' . $volum . '</p>';
    $offer_html .= '<p class="detail alignleft">' . $produsent . '</p>';

    // Use stuff from output buffer instead of wpfp_link() method.
    $offer_html .= $wpfp_html;

    $offer_html .= '</div';

    return $offer_html;
}

// Don't forget to handle active output buffering!
ob_end_flush();
?>
Informant
you shauld put the ob_start and ob_end_flush within th efunction as its only needed within that scope.
RobertPitt
Fantastic! Thanks for teaching me about output buffering :-)
Espen Arnoy
ob_start and ob_end_flush outside the method scope should indicate that those method could influence other code parts! You should make sure that there's no other output buffering active or you should handle that accordingly!
Informant
Please consider kemps answer as the way to go. output buffering as a workaround is just evil, when you are offered to pass a parameter that makes the function return its value instead of echo it.
Sebastian Hoitz
A: 

Try printing out (using echo) the whole string instead.

echo "<div class=\"box middle offer alignleft\">\n<p class=\"detail alignleft\">" . $volum . "</p>\n<p class=\"detail alignleft\">" . $produsent . "</p>\n" . wpfp_link() . "</div>";
Ruel
A: 

The wpfp_link function is probably echoing the HTML instead of returning it. You could use output buffering get the HTML as a string.

$offer_html = '<div class="box middle offer alignleft">';
$offer_html .= '<p class="detail alignleft">' . $volum . '</p>';
$offer_html .= '<p class="detail alignleft">' . $produsent . '</p>';
ob_start();
wpfp_link();
$offer_html .= ob_get_clean();
$offer_html .= '</div';

return $offer_html;
Matt Barry
A: 

Is this the cause of any problems:

$offer_html .= '</div'; 

should surely be

$offer_html .= '</div>'; 
Mark Baker
A: 

I apologize for answering twice, I noticed a bug with the code for chosen answer. Consider the following code:

<?php
function wpfp_link() {
    static $count = 0;
    echo '<img class="wpfp-img" title="Favorite" alt="Favorite" src="http://localhost:8888/wordpress/wp-content/plugins/wp-favorite-posts/img/remove.png"&gt;' . ($count++) ."\n";
}
// Turn on outbut buffering
ob_start();


function your_function()
{
    // Fill outbut buffer
    wpfp_link();

    // Fetch and clean output buffer
    $wpfp_html = ob_get_clean();
    var_dump($wpfp_html);
    $offer_html = '<div class="box middle offer alignleft">';
    $offer_html .= '<p class="detail alignleft">' . $volum . '</p>';
    $offer_html .= '<p class="detail alignleft">' . $produsent . '</p>';

    // Use stuff from output buffer instead of wpfp_link() method.
    $offer_html .= $wpfp_html;

    $offer_html .= '</div>';

    return $offer_html;
}

// Don't forget to handle active output buffering!
ob_end_flush();
echo your_function();
echo your_function();
echo your_function();
echo your_function();
echo your_function();
echo your_function();
echo your_function();

?>

The variable $wpfp_html has a value of false for each call of your_function because output buffering is turned off after ob_end_flush is called. ob_start() needs to be called each time prior to ob_get_clean() for the output buffer to be active.

I would've posted a comment to your answer, Informant but I don't have a high enough reputation.

Matt Barry
+2  A: 

There is another - and I believe better - way to solve this. Looking at the source code of the plugin containing that function (WP Favorite Posts) you can see that the wpfp_link() function accepts various arguments, the first of which is a flag that changes its behavior between printing its output and returning it.

function wpfp_link( $return = 0, $action = "", $show_span = 1, $args = array() ) {
    global $post;
    $post_id = $post->ID;
    extract($args);
    if ($show_span)
        $str = "<span class='wpfp-span'>";
    $str .= wpfp_before_link_img();
    $str .= wpfp_loading_img();
    $wpfp_options = wpfp_get_options();
    if ($action == "remove"):
        $str .= wpfp_link_html($post_id, wpfp_get_option('remove_favorite'), "remove");
    elseif ($action == "add"):
        $str .= wpfp_link_html($post_id, wpfp_get_option('add_favorite'), "add");
    elseif (wpfp_check_favorited($post_id)):
        $str .= wpfp_link_html($post_id, wpfp_get_option('remove_favorite'), "remove");
    else:
        $str .= wpfp_link_html($post_id, wpfp_get_option('add_favorite'), "add");
    endif;
    if ($show_span)
        $str .= "</span>";
    if ($return) { return $str; } else { echo $str; }
}

so

wpfp_link(TRUE);

should act as you expected.

I checked the source code but this is probably documented somewhere in the plugin information.

kemp
Thanks for going the extra mile to figure out!
Espen Arnoy