Шорткод выводится в начале the_content

19 нояб. 2012 г., 00:05:59
Просмотры: 2.62K
Голосов: 7

Шорткод, созданный этой функцией (список всех сайтов в мультисайте), выводится в начале контента в цикле, независимо от его расположения в редакторе.

Я изучил похожие вопросы и ответы на WPSE и понимаю, что проблема связана с использованием echo вместо return в функции, но просто заменить echo на return в функции ниже недостаточно. Или добавить echo=0 с функцией WP типа wp_list_pages().

Есть идеи? Где именно функция должна возвращать значение вместо вывода?

// Вывод одного элемента меню
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) != '/') {
            // Примечание: я добавил "/" в конец URL, потому что WordPress
            // не делал этого автоматически в версии 3.0.4
            $url .= '/';
        }
        echo '<a href="' . $url . '">' . $title . '</a>';
        if ($id == $blog_id) {
            echo '</strong>';
        }
        echo '</li>';
    }
}

// Вывод всего меню
// Если $link_self false, пропускаем текущий сайт - используется для отображения меню на главной странице
function projects_menu($link_self = true)
{
    global $wpdb;

    echo '<ul>';

    projects_menu_entry(1, 'Главная', $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>';
}

// Добавляем шорткод [bloglist]

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

add_shortcode('bloglist', 'bloglist_shortcode');
1
Комментарии

возможный дубликат вопроса Шорткод всегда отображается в верхней части страницы

Michael Michael
19 нояб. 2012 г. 00:20:57
Все ответы на вопрос 4
1
10

Все функции должны возвращать строку, не следует использовать echo где-либо. Перепишите функции, используя внутреннюю переменную для работы со строками и возвращайте её:

// Вывод отдельного пункта меню
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;
}

// Вывод всего меню
// Если $link_self равен false, пропускаем текущий сайт - используется для отображения меню на главной странице
function projects_menu($link_self = true)
{
    global $wpdb;
    $out = '<ul>';

    $out .= projects_menu_entry(1, 'Главная', $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;
}

// Добавляет шорткод [bloglist]

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

add_shortcode('bloglist', 'bloglist_shortcode');

Для похожего, расширенного примера см.: Как возвращать содержимое цикла.

19 нояб. 2012 г. 00:16:00
Комментарии

Ах, вы правы; это логично. Хорошее решение. Спасибо.

markratledge markratledge
19 нояб. 2012 г. 00:20:03
1

Вы не можете заменить экземпляры echo, потому что можете вернуть значение только один раз. Вам нужно собрать строку и вернуть её.

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>';
        }
    // и так далее
    $ret .= '</ul>';
    return $ret;
}

Сделайте это для обеих функций, и я ожидаю, что это заработает. Извините, если я что-то кардинально неправильно понял.

19 нояб. 2012 г. 00:18:01
Комментарии

Спасибо, и ты прав. toscho опередил тебя на две минуты.

markratledge markratledge
19 нояб. 2012 г. 00:20:43
1

Есть идеи? Где функция, которая должна возвращать значение вместо вывода через echo?

Я предлагаю альтернативное решение, которое не требует замены экземпляров echo или построения возвращаемой строки.

Вы можете включить буферизацию вывода и вернуть буфер в виде строки.

Добавьте ob_start() в начало функции перед любым вызовом echo.

В конце функции добавьте:

$response = ob_get_contents();
ob_end_clean();
return $response;
19 нояб. 2012 г. 00:23:22
Комментарии

Этот метод отлично работает; я наконец-то попробовал его. Спасибо.

markratledge markratledge
29 авг. 2013 г. 07:18:20
0

Краткий и быстрый ответ:

Вам следует использовать return для вывода, а не echo.

$output = 'первый';
$output .= 'второй'; // обратите внимание на точку (.=) после первой переменной
$output .= 'третий';
return $output;
10 мар. 2019 г. 16:39:36