El shortcode se muestra en la parte superior del the_content

19 nov 2012, 00:05:59
Vistas: 2.62K
Votos: 7

El shortcode producido por esta función - una lista de todos los sitios en una red multisitio - se muestra arriba del contenido en el loop, sin importar dónde se coloque en el editor.

He revisado otras preguntas y respuestas relacionadas en WPSE y entiendo que tiene que ver con que la función usa echo en lugar de return, pero no es tan simple como reemplazar las instancias de echo con return en la función de abajo. O añadir echo=0 con una función de WP como wp_list_pages()

¿Alguna idea? ¿Dónde está la función que necesita devolver un valor en lugar de hacer echo?

// Mostrar un elemento individual del menú
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) != '/') {
            // Nota: Añadí un "/" al final de la URL porque WordPress
            // no lo hacía automáticamente en la versión 3.0.4
            $url .= '/';
        }
        echo '<a href="' . $url . '">' . $title . '</a>';
        if ($id == $blog_id) {
            echo '</strong>';
        }
        echo '</li>';
    }
}

// Mostrar el menú completo
// Si $link_self es false, omite el sitio actual - usado para mostrar el menú en la página principal
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>';
}

// Añade un shortcode [bloglist]

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

add_shortcode('bloglist', 'bloglist_shortcode');
1
Comentarios

posible duplicado de El shortcode siempre se muestra en la parte superior de la página

Michael Michael
19 nov 2012 00:20:57
Todas las respuestas a la pregunta 4
1
10

Todas las funciones deben retornar una cadena, no deberías usar echo en ningún lugar. Reescribe las funciones, usa una variable interna para manejar las cadenas y retorna esa:

// Mostrar un solo elemento del menú
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;
}

// Mostrar el menú completo
// Si $link_self es falso, omite el sitio actual - usado para mostrar el menú en la página de inicio
function projects_menu($link_self = true)
{
    global $wpdb;
    $out = '<ul>';

    $out .= projects_menu_entry(1, 'Inicio', $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;
}

// Añade un shortcode [listadeblogs]
function bloglist_shortcode($atts)
{
    return projects_menu(false);
}

add_shortcode('listadeblogs', 'bloglist_shortcode');

Para un ejemplo similar ampliado ver: Cómo retornar contenidos del loop.

19 nov 2012 00:16:00
Comentarios

Ah, tienes razón; eso tiene sentido. Buena solución. Gracias.

markratledge markratledge
19 nov 2012 00:20:03
1

No puedes reemplazar las instancias de echo porque solo puedes retornar una vez. Necesitas construir una cadena y retornarla.

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>';
        }
    // y así sucesivamente
    $ret .= '</ul>';
    return $ret;
}

Haz eso para ambas funciones y esperaría que esto funcione. Mis disculpas si he leído algo incorrectamente.

19 nov 2012 00:18:01
Comentarios

Gracias, y tienes razón. toscho te ganó por dos minutos.

markratledge markratledge
19 nov 2012 00:20:43
1

¿Alguna idea? ¿Dónde está la función que necesita devolverse en lugar de hacer echo?

Voy a ofrecer una solución alternativa que no requiere que reemplaces instancias de echo o construyas una cadena de retorno.

Puedes activar el almacenamiento en búfer de salida y devolver el búfer como una cadena.

Añade ob_start() al principio de la función antes de cualquier llamada a echo.

Al final de la función añade:

$response = ob_get_contents();
ob_end_clean();
return $response;
19 nov 2012 00:23:22
Comentarios

Este método funciona muy bien; finalmente me decidí a probarlo. Gracias.

markratledge markratledge
29 ago 2013 07:18:20
0

Respuesta corta y rápida:

Debes return tu salida y no echo.

$output = 'primero';
$output .= 'segundo'; //observa el punto (.=) después de la primera variable
$output .= 'tercero';
return $output;
10 mar 2019 16:39:36