[Solved] Shortcode outputs at the top of the_content


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, "https://wordpress.stackexchange.com/" );

        $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.

1

solved Shortcode outputs at the top of the_content