Shortcode outputs at the top of the_content

admin2025-06-02  0

The shortcode produced by this function - a list of all sites in a multisite - outputs above the content in the loop, no matter where it is placed in the editor.

I've looked at the other related questions and answers on WPSE and realize that it has to do with the function using echo instead of return, but it's not as easy as replacing the instances of echo with return in the function below. Or adding echo=0 with a WP function like wp_list_pages()

Any ideas? Where is the function that needs to be returned instead of echoed?

// Output a single menu item
function projects_menu_entry($id, $title, $link_self)
{
    global $blog_id;
    if ($link_self || $id != $blog_id) {
        echo '<li>';
        if ($id == $blog_id) {
            echo '<strong>';
        }
        $url = get_home_url($id);
        if (substr($url, -1) != '/') {
            // Note: I added a "/" to the end of the URL because WordPress
            // wasn't doing that automatically in v3.0.4
            $url .= '/';
        }
        echo '<a href="' . $url . '">' . $title . '</a>';
        if ($id == $blog_id) {
            echo '</strong>';
        }
        echo '</li>';
    }
}

// Output the whole menu
// If $link_self is false, skip the current site - used to display the menu on the homepage
function projects_menu($link_self = true)
{
    global $wpdb;

    echo '<ul>';

    projects_menu_entry(1, 'Home', $link_self);

    $blogs = $wpdb->get_results("
        SELECT blog_id
        FROM {$wpdb->blogs}
        WHERE site_id = '{$wpdb->siteid}'
        AND spam = '0'
        AND deleted = '0'
        AND archived = '0'
        AND blog_id != 1
    ");

    $sites = array();
    foreach ($blogs as $blog) {
        $sites[$blog->blog_id] = get_blog_option($blog->blog_id, 'blogname');
    }

    natsort($sites);
    foreach ($sites as $blog_id => $blog_title) {
        projects_menu_entry($blog_id, $blog_title, $link_self);
    }
    echo '</ul>';
}

// Adds a [bloglist] shortcode

function bloglist_shortcode($atts)
{
    projects_menu(false);
}

add_shortcode('bloglist', 'bloglist_shortcode');

The shortcode produced by this function - a list of all sites in a multisite - outputs above the content in the loop, no matter where it is placed in the editor.

I've looked at the other related questions and answers on WPSE and realize that it has to do with the function using echo instead of return, but it's not as easy as replacing the instances of echo with return in the function below. Or adding echo=0 with a WP function like wp_list_pages()

Any ideas? Where is the function that needs to be returned instead of echoed?

// Output a single menu item
function projects_menu_entry($id, $title, $link_self)
{
    global $blog_id;
    if ($link_self || $id != $blog_id) {
        echo '<li>';
        if ($id == $blog_id) {
            echo '<strong>';
        }
        $url = get_home_url($id);
        if (substr($url, -1) != '/') {
            // Note: I added a "/" to the end of the URL because WordPress
            // wasn't doing that automatically in v3.0.4
            $url .= '/';
        }
        echo '<a href="' . $url . '">' . $title . '</a>';
        if ($id == $blog_id) {
            echo '</strong>';
        }
        echo '</li>';
    }
}

// Output the whole menu
// If $link_self is false, skip the current site - used to display the menu on the homepage
function projects_menu($link_self = true)
{
    global $wpdb;

    echo '<ul>';

    projects_menu_entry(1, 'Home', $link_self);

    $blogs = $wpdb->get_results("
        SELECT blog_id
        FROM {$wpdb->blogs}
        WHERE site_id = '{$wpdb->siteid}'
        AND spam = '0'
        AND deleted = '0'
        AND archived = '0'
        AND blog_id != 1
    ");

    $sites = array();
    foreach ($blogs as $blog) {
        $sites[$blog->blog_id] = get_blog_option($blog->blog_id, 'blogname');
    }

    natsort($sites);
    foreach ($sites as $blog_id => $blog_title) {
        projects_menu_entry($blog_id, $blog_title, $link_self);
    }
    echo '</ul>';
}

// Adds a [bloglist] shortcode

function bloglist_shortcode($atts)
{
    projects_menu(false);
}

add_shortcode('bloglist', 'bloglist_shortcode');
Share Improve this question edited Jan 27, 2013 at 9:58 fuxia 107k39 gold badges255 silver badges461 bronze badges asked Nov 18, 2012 at 22:05 markratledgemarkratledge 8,7356 gold badges40 silver badges62 bronze badges 1
  • possible duplicate of Shortcode always displaying at the top of the page – Michael Commented Nov 18, 2012 at 22:20
Add a comment  | 

4 Answers 4

Reset to default 10

All functions have to return a string, you should not use echo anywhere. Rewrite the functions, use an internal variable to handle the strings and return that:

// Output a single menu item
function projects_menu_entry($id, $title, $link_self)
{
    global $blog_id;
    $out = '';

    if ($link_self || $id != $blog_id) {
        $out .= '<li>';
        if ($id == $blog_id) {
            $out .= '<strong>';
        }
        $url = get_home_url( $id, '/' );

        $out .= '<a href="' . $url . '">' . $title . '</a>';
        if ($id == $blog_id) {
            $out .= '</strong>';
        }

        $out .= '</li>';
    }

    return $out;
}

// Output the whole menu
// If $link_self is false, skip the current site - used to display the menu on the homepage
function projects_menu($link_self = true)
{
    global $wpdb;
    $out = '<ul>';

    $out .= projects_menu_entry(1, 'Home', $link_self);

    $blogs = $wpdb->get_results("
        SELECT blog_id
        FROM {$wpdb->blogs}
        WHERE site_id = '{$wpdb->siteid}'
        AND spam = '0'
        AND deleted = '0'
        AND archived = '0'
        AND blog_id != 1
    ");

    $sites = array();
    foreach ($blogs as $blog) {
        $sites[$blog->blog_id] = get_blog_option($blog->blog_id, 'blogname');
    }

    natsort($sites);
    foreach ($sites as $blog_id => $blog_title) {
        $out .= projects_menu_entry($blog_id, $blog_title, $link_self);
    }
    $out .= '</ul>';

    return $out;
}

// Adds a [bloglist] shortcode

function bloglist_shortcode($atts)
{
    return projects_menu(false);
}

add_shortcode('bloglist', 'bloglist_shortcode');

For a similar, extended example see: How to return loop contents.

You can't replace the instances of echo because you can only return once. You need to build a string and return that.

function projects_menu_entry($id, $title, $link_self)
{
    global $blog_id;
    $ret = '';
    if ($link_self || $id != $blog_id) {
        $ret .= '<li>';
        if ($id == $blog_id) {
            $ret .= '<strong>';
        }
    // and so on
    $ret .= '</ul>';
    return $ret;
}

Do that for both functions and I would expect this to work. Apologies if I have grossly misread something.

Any ideas? Where is the function that needs to be returned instead of echoed?

I'm going to offer an alternative solution that does not require you to replace instances of echo or build a return string.

You can turn on output buffering and return the buffer as a string.

Add ob_start() to the beginning of the function before any echo call.

at the end of the function add:

$response = ob_get_contents();
ob_end_clean();
return $response;

Short and quick answer:

You should return your output and not echo it.

$output = 'first';
$output .= 'second'; //notice the dot (.=) after the first variable
$output .= 'third';
return $output;
转载请注明原文地址:http://conceptsofalgorithm.com/Algorithm/1748823162a314017.html

最新回复(0)