Как скрыть часть контента от незарегистрированных пользователей в WordPress при помощи шорткодов

Очень часто на форумах можно встретить уведомления «Ссылки могут видеть только зарегистрированные пользователи» или «Скачивание файлов доступно только для зарегистрированных».

Очевидно, что весь контент (весь пост полностью) закрыть легко, всего лишь добавив условие в файл темы, а я вам покажу, как скрывать конкретные участки поста, будь то предложение, ссылка или картинка.

Рассмотренные в этой статье примеры закрывают контент не только от неавторизованных посетителей сайта, но и от поисковиков.

Отображение контента только для зарегистрированных пользователей

Сначала создаем шорткод, вставив этот код в functions.php текущей темы:

function true_logged_in_user_content( $atts, $content = null ) {
	if ( is_user_logged_in() && !is_null( $content ) && !is_feed() ) {
		return $content;
	}
	return ''; // тут в кавычках можете написать сообщение об ошибке, отображающееся для пользователей, у которых нет доступа, можно использовать HTML.
}
 
add_shortcode( 'member', 'true_logged_in_user_content' );

Теперь второй шаг, при написании поста, когда вы захотите скрыть какую-то часть текста, просто поместите его между [member] и [/member], например:

[member]
 
Этот текст увидят только зарегистрированные пользователи.
 
[/member]

Сюда можно засунуть не только текст, но также ссылки (например ограничить доступ к скачиванию файлов), картинки и прочий HTML.

Отображение контента в зависимости от роли пользователя

Тут действует тот же самый принцип, но только с некоторыми усовершенствованиями. Опять начинаем с создания шорткода через functions.php:

function true_content_by_user_cap( $attr, $content = null ) {
	// массив со значениями по умолчанию, которые будут применяться, если в шорткоде не был указан параметр
	$defaults = array(
		'capability' => 'read'
	);
	extract( shortcode_atts( $defaults, $attr ) );
	if ( current_user_can( $capability ) && !is_null( $content ) && !is_feed() ) {
		return $content;
	}
	return ''; // указываем сообщение об ошибке если нужно
}
 
add_shortcode( 'access', 'true_content_by_user_cap' );

Сам шорткод на странице редактирования поста будет выглядеть следующим образом:

[access capability="edit_posts"]
 
Эта часть контента видна пользователям, которые могут редактировать записи.
 
[/access]

А в этом случае будут применяться значения по умолчанию из массива $defaults:

[access]
 
Это сообщение увидят все зарегистрированные пользователи.
 
[/access]

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

Миша

В последние годы я долго не знал, что мне делать с сайтом misha.blog, ведь он практически не приносит никакого профита, но недавно я осознал, что моя миссия – способствовать распространению WordPress. Ведь WordPress – это лучший движок для разработки сайтов – как для тех, кто готов использовать заложенную структуру этой CMS, так и для тех, кто предпочитает headless решения.

Сам же я впервые познакомился с WordPress в 2009 году. Организатор WordCamp. Преподаватель в школах Epic Skills и LoftSchool.

Если вам нужна помощь с вашим сайтом или может даже разработка с нуля на WordPress / WooCommerce — пишите. Я и моя команда сделаем вам всё на лучшем уровне.

Комментарии — 58

Комментирование этого поста более не доступно.
  • adarka 22 апреля 2013 #

    спасибо! то , что надо! перекопала кучу плагинов, а тут такой простой и изящный метод!

    • Миша 23 апреля 2013 #

      рад, что смог помочь)

  • Алексей 16 мая 2013 #

    Почему то после вставки кода а functions.php и вывода шорткода в посте-ничего не происходит.только код не активный какой то-весь черный без подсветки.И этот код всплывает сверху в админке.Помогите разобраться в чем проблема...

    • Миша 20 мая 2013 #

      это значит, что перед кодом надо добавить

      <?php
    • Миша 20 мая 2013 #

      сорри за долгий ответ.

  • Алексей 20 мая 2013 #

    Миша спасибо я уже разобрался) Действительно в этом проблема была...

    • Миша 21 мая 2013 #

      ну я так и думал, ведь я почти через 5 дней ответил, реально не было возможности зайти на сайт и проверить комменты,
      в след. раз постараюсь отвечать более быстро))

  • Алексей 22 июня 2013 #

    Миша подскажи пожалуйста...
    А вот то же самое можно реализовать на Joomla ???
    Очень хотелось бы...

    • Миша 23 июня 2013 #

      я джумлой не занимаюсь, но по идее должна быть такая возможность (или плагин какой-нибудь)

  • Виктор 7 сентября 2013 #

    Добрый день! У меня противоположная проблема, после работы со страничкой вдруг стала активна эта функция входа на страничку через пароль. ПОдскажите как убрать это и сделать как прежде свободный вход

  • Программист 7 октября 2013 #

    НЕ РАБОТАЕТ! Не в коем случае не пробуйте так сделать!

    • Роман 7 октября 2013 #

      перед кодом и после вставь

    • Роман 7 октября 2013 #

      < ? php

  • Алексей 7 октября 2013 #

    Все работает,чего ты гонишь... Я на трех блогах проверял и никаких проблем...

  • Роман 7 октября 2013 #

    Подскажите, как сделать так, чтобы скрыть один пункт в меню в шапке? На сайте есть меню: Главная Документы Контакты. Нужно сделать так, чтобы пункт "документы" становился видным после авторизации, а для гостей был скрыт.

    • Миша 10 октября 2013 #

      Добрый день.
      всё зависит от того, каким образом выводится это меню

  • Павел 7 января 2014 #

    Здравствуйте, Михаил!

    Это отличное решение, но у него есть один существенный недостаток, поиск отлично видит скрытый контент и выводит страницу где он расположен, хоть сам блок и не виден.

    Скажите, как сделать этот скрытый блок недоступным поиску?

    • Миша 7 января 2014 #

      Добрый день!

      чтобы сказать точно, нужно смотреть и тестировать, а так мне кажется вам следует в шаблоне поиска заменить get_the_content() на the_content(). Теоретически.

  • Олег 16 мая 2014 #

    Михаил, добрый день.

    У меня почему то не работает Ваш вариант.

    Вставил код в Functions.php в конец файла.

    До и после поставил < ? php

    На странице своей обрамил текст [member] Text [/member]
    но хоть регистрированный, хоть нет пользователь все равно видно текст.
    И кстати видно и тег [member] вокруг текста.

    В чем может быть проблема?

    • Сергей 26 августа 2014 #

      после кода надо наверное ?> ставить

  • hardcore 28 декабря 2014 #

    Михаил, добрый день.
    А для полного сайта(контента) можете показать пример? Типа гости только видели одну статическую страницу. Спасибо!

    • Миша 29 декабря 2014 #

      Добрый день!
      Вот универсальное условие для администраторов / редакторов:

      if ( current_user_can( 'edit_posts' ) ) {
       
      }

      А вот для авторизованных пользователей:

      if ( is_user_logged_in() ) {
       
      }
  • Ильяс 16 февраля 2015 #

    Спасибо большое,все просто и все работает 🙂

  • FROLOff 31 марта 2015 #

    Все перепробовал. Инструмент отнюдь не универсальный.

    • orion833000 31 марта 2015 #

      А что тебе нужно универсального? Миша дал рабочий вариант с помощью него я не 1 тысячу рубликов зарабатывал... нужен универсальный - купи Wish List Member и танцуй с бубном.

      • FROLOff 1 апреля 2015 #

        А что тебе нужно от меня? Считаешь нужной мне ту информацию, которую выдал под комментарием?:)

  • FROLOff 1 апреля 2015 #

    Михаил, может, подскажете, почему у меня все-таки не получается:

    Установил шорткод, и он отлично работает на страницах. Вот код из файла functions.php:

    add_shortcode( 'member', 'true_logged_in_user_content' );
    function true_logged_in_user_content( $atts, $content = null ) {
        if ( is_user_logged_in() && !is_null( $content ) && !is_feed() ) {
            return $content;
        }
        return 'Требуется регистрация';
    }

    Однако на странице редактирования шаблона (page.php) обычный шорткод не работает. Использую следующий вариант: Текст, который нужно скрыть, и получается вот такое: Требуется регистрацияТекст, который нужно скрыть. Естественно, фраза "Текст, который нужно скрыть" и должна скрываться фразой "Требуется регистрация".

    Обычный вариант [member]Текст[/member] не работает, естественно. Как же "зажать" текст в эти теги на php-странице?

    • Миша 1 апреля 2015 #

      он отлично работает на страницах

      Однако на странице редактирования шаблона (page.php) обычный шорткод не работает

      Так где он в итоге у вас работает, а где нет?

      • FROLOff 1 апреля 2015 #

        Работал в записях, не работал на страницах. Разобрался. Спасибо за пост.
        Чтобы добавить "универсальности", советую отредактировать статью. Добавьте прямой пример рабочего кода для страниц .php:

        <?php echo do_shortcode('[member]Текст[/member]');?>
        • Миша 1 апреля 2015 #

          Рад, что вы разобрались. Рекомендую ознакомиться с теорией, как работают шорткоды truemisha.ru/blog/wordpress/shortcodes.html.

          • Людмила 19 апреля 2015 #

            Ну спасибо, пошла Вордпресс переустанавливать. Все слетело - пустая страница.

            • Миша 19 апреля 2015 #

              Уверяю вас, переустанавливать WP совсем ни к чему. Во-первых, можете вставить код именно после <?php (почему-то мне кажется, что проблема в этом), во-вторых, вы можете просто удалить мой код, в третьих, вы можете зайти в wp-config.php, включить WP_DEBUG и посмотреть, где именно возникла ошибка 😛

              • Алексей Фатькин 19 апреля 2015 #

                Миша в точку сказал... зачем WP то переустанавливать?

              • Людмила 19 апреля 2015 #

                Да просто я только установила вордпресс, хостинг мне не знакомый, пока не могу понять как попасть в файловый менеджер, чтобы менять файлы, спасибо за совет, но быстрее будет переустановить заново.

  • SuperSanek 15 июля 2015 #

    все работает на 100% , скрывает кнопки например, подскажите, как сделать ссылку на страницу регистрации прямо с надписи которая закрывает контент "зарегистрируйтесь бла бла..."

    • Миша 15 июля 2015 #

      Так не пробовали?

      <a href="http://адрес-сайта/wp-login.php?action=register">зарегистрируйтесь</a>
      • SuperSanek 16 июля 2015 #

        не пробовал, учусь только пробовать,затягивает)

  • Алексей 3 сентября 2015 #

    Проблема в отображении текста ошибки, обвожу тегами, текст пропадает, но уведомления нет на месте скрытого текста

    • Миша 4 сентября 2015 #

      Можно взглянуть на вашу функцию?

  • Павел 8 ноября 2015 #

    Михаил, здравствуйте!

    Пытаюсь сделать скрытый контейнер только для зарегистрированных пользователей без шорткода, но пока не получается... Подскажите как нужно? Вот пока что накропал:

    function private_content( $content ) {
    	if ( is_user_logged_in() && !is_null( $content ) && !is_feed() ) {
    		return '<div class="private">' . $content . '</div>';
    		} else {
    		return '';
    	}
    }
     
    add_filter ('the_content',  'private_content');

    Но он прячет не содержимое контейнера .private, а вообще всё содержимое записи...

    • Павел 8 ноября 2015 #

      Ну, чтобы не отвлекать маэстро глупостями, пишу ответ:

      function private_content( $content ) {
       
      	if ( is_user_logged_in() && !is_null( $content ) && !is_feed() ) {
      		return $content;
      		} else {
      		return preg_replace('/(<div class="private">.*?<\/div>)/uis', '', $content);
      	}
       
      }
       
      add_filter ('the_content',  'private_content');

      Кто-нибудь знает, как выбросит содержимое этого контейнера и из поиска тоже?

      • Миша 9 ноября 2015 #

        Здравствуйте!
        А в поиске тоже функцией the_content() выводится?

  • Musicman 6 декабря 2015 #

    Здравствуйте, Михаил. Код работает хорошо, но возникла ситуация.
    Я обернул в данные теги контент, где содержатся другие теги с прямыми скобками, в частности, я спрятал таблицу, в ячейках которой вставлены аудиозаписи в теге [audio]Музон[/audio]
    В итоге незарегенные все правильно - не видят ничего, а вот зареганные видят исходный код контента, ни плееров, ни ссылок. Что можно придумать?

    • Миша 6 декабря 2015 #

      Здравствуйте!
      Вот в этой статье, в самом низу, о том, как наложить фильтры.

      • Musicman 12 декабря 2015 #

        Спасибо, Михаил, благодаря этой статье начал раскуривать коды. Добра Вам

  • Дима 26 января 2016 #

    Подскажите пожалуйста, возможно ли сделать этот метод для мультиязычного сайта? Установлен WP Multisite, русский и английский, файл functions.php один для всех. Т. е. или на английском сайте будет отображаться русское оповещение о регистрации, или на русском английское. Ну и ссылку соответственно не вставить о регистрации. Была идея написать уведомление через слеш, мол: "Регистрируйся/Register", но всё же.

    • Миша 26 января 2016 #

      Возможно, просто почитайте про функции работы с мультисайтом. У меня на блоге к сожалению об этом совсем немного.

      • Дима 26 января 2016 #

        Благодарю за быстрый ответ. Вышел из положения дублированием функции, добавил: "true_logged_in_user_content_en".

      • Дима 26 января 2016 #

        Прошу прощения, забыл спросить, а форматирование сообщения об ошибке возможно? Если да, подскажите пару трюков пожалуйста, изменить цвет, выделить жирным...

        • Миша 27 января 2016 #

          Так через CSS 🙂

          • Дима 31 января 2016 #

            Style.css? Открываем и... Как сослаться на функцию может подскажете? Методом тыка пытался менять стили, но меняется весь текст(

            • Миша 31 января 2016 #

              Там, где нужно указать сообщение об ошибке — оберните его например в

              <span id="errorm">Сообщение об ошибке.</span>

              А потом в стилях:

              #errorm{
               
              }
              • Дима 31 января 2016 #

                Огромная благодарность! Всё работает как часы швейцарские! Всего Вам наилучшего!

  • Иван 27 августа 2016 #

    Миш, объясни, что ты делаешь этой строчкой:

    extract( shortcode_atts( $defaults, $attr ) );

    Я давно читал об этой функции, но что то не могу понять, что она здесь делает

    • Миша 28 августа 2016 #

      Привет,

      функция shortcode_atts() заменяет элементы массива $defaults на элементы из $atts, но только в том случае и только на те, которые указаны.

      Функция extract() "распечатывает" массив в переменные, то есть $attr['hello'] превратится в $hello и т.д.

      • Иван 28 августа 2016 #

        Спасибо, понял!

  • Saitozavisim 22 ноября 2019 #

    Здравствуйте! А как вывести кастомное поле внутри шорткода?
    Это поле можно вывести шорткодом [acf field="name"]

    То есть как вместо контента поставить этот шорткод?)

    • Миша 28 ноября 2019 #

      Добрый день!

      Ну шорткод внутри шорткода, ez