Вопрос или проблема
Я хочу скрыть определенные посты от всех, кто не авторизован. Я пробовал плагин Restrict Content (RC), но он лишь скрывал содержимое постов, я хочу полностью исключить пост.
Используя RC как основу, я пробовал следующее:
function hideFromUnknownUsers($postObject) {
$rcUserLevel = get_post_meta ( $postObject->ID, 'rcUserLevel', true );
if(have_posts())
{
if (!(
!current_user_can ( 'read' ) &&
(
$rcUserLevel == 'Administrator' ||
$rcUserLevel == 'Editor' ||
$rcUserLevel == 'Author' ||
$rcUserLevel == 'Contributor' ||
$rcUserLevel == 'Subscriber'
)
)) {
the_post();
}
}
}
add_action ( 'the_post', 'hideFromUnknownUsers' );
У этого подхода есть системный недостаток. Последний пост нельзя игнорировать. Однако я могу с этим смириться на данный момент. Еще одна проблема в том, что это вызывает бесконечный цикл, повторяя одни и те же посты снова и снова. Я обнаружил, что это происходит из-за того, что have_posts()
не только сообщает нам о том, что достигнут конец последнего поста, но и имеет побочный эффект, что счетчик постов также сбрасывается, что мешает моему основному циклу достигнуть конца. Создание have_posts()
, которое было бы ненавязчивым, оказалось сложным, поскольку я не смог понять, как получить доступ к $wp_query->current_post
и $wp_query->post_count
из плагина.
Одно из решений могло бы быть в том, чтобы иметь вышеуказанную логику непосредственно в PHP файлах тем, но это придется повторять повсюду, где я намерен обращаться к посту, что делает это обременительным и подверженным ошибкам.
Есть ли другой способ скрыть определенные посты от неизвестных пользователей?
Работа с ролями пользователей, вероятно, будет наиболее надежным решением, однако быстрый и простоватый подход будет заключаться в том, чтобы установить метаданные постов, чтобы отметить посты, которые должны быть скрыты, а затем добавить мета-запрос к запросам постов, используя хук pre_get_posts
для ограничения результатов лишь несекретными постами для незарегистрированных пользователей.
Следующее ограничит все посты, запрашиваемые для незарегистрированных посетителей, теми, которые либо не имеют связанных метаданных hide_from_guests
, либо имеют эти метаданные, установленные на 'false'
:
function wpse225120_hide_posts_from_guests( $query ) {
// Если пользователь авторизован, выходите из функции сейчас.
if( is_user_logged_in() )
return;
// Получите текущий мета-запрос, чтобы мы могли его изменить, а не перезаписать
$meta_query = $query->get( 'meta_query' );
// Создайте мета-запрос, фильтрующий скрытые посты
$hidden_meta_query = array(
'relation' => 'OR',
array(
'key' => 'hide_from_guests',
'value' => 'false'
),
array(
'key' => 'hide_from_guests',
'compare' => 'NOT_EXISTS'
)
);
// Если мета-запроса еще нет, предоставьте один для скрытых постов и выходите
if( ! is_array( $meta_query ) || empty( $meta_query ) ) {
$query->set( 'meta_query', $hidden_meta_query );
return;
}
// Если существует существующий мета-запрос, измените его, чтобы поддерживать наш новый мета-запрос скрытых постов
// как основное условие 'AND', если это необходимо
if( isset( $meta_query[ 'relation' ] ) && 'OR' === $meta_query[ 'relation' ] )
$meta_query = array(
'relation' => 'AND',
$meta_query
);
}
// Добавьте мета-запрос скрытых постов и перезапишите старый мета-запрос $query
$meta_query[] = $hidden_meta_query;
$query->set( 'meta_query', $meta_query );
}
add_action( 'pre_get_posts', 'wpse225120_hide_posts_from_guests' );
Примечание о том, что глобальное изменение каждого запроса таким образом обычно считается плохой практикой. Если возможно, используйте
is_main_query()
и другие условные теги, чтобы ограничить изменения запросов только релевантными запросами, чтобы предотвратить неожиданные поведения и влияние на производительность.
Метаданные постов 'hide_from_guests'
могут быть установлены на индивидульные посты с помощью интерфейса пользовательских полей, функций метаданных постов или реализуя пользовательский метабокс и прикрепляя его к соответствующим типам постов, среди прочих способов.
Используйте этот код в файле functions.php вашей дочерней темы.
// Скрыть для незарегистрированных пользователей (публичные посетители)
function bp_logged_out_page_template_redirect() {
if( ! is_user_logged_in() &&
is_page( 'members' )||
is_page( 'activity' ) ||
bp_is_user()
) {
wp_redirect( home_url( '/register/' ) ); exit();
}
}
add_action( 'template_redirect', 'bp_logged_out_page_template_redirect' );
Вышеуказанный фрагмент сделает следующее:
ЕСЛИ пользователь не авторизован..
И имя страницы — ‘members’ ИЛИ ‘activity’ ИЛИ bp-profile-page..
ТОГДА он будет перенаправлен на страницу РЕГИСТРАЦИИ.
Ответ или решение
Вопрос о скрытии постов от незарегистрированных пользователей является актуальной задачей для многих веб-разработчиков, использующих WordPress как платформу для ведения сайтов. В данной статье мы рассмотрим несколько способов решения этой проблемы и предложим оптимальный подход, который не только будет эффективным, но и не повлияет на производительность сайта.
Подходы к решению задачи
-
Использование плагина Restrict Content (RC):
Вы уже использовали плагин RC, однако его возможности ограничиваются лишь скрытием содержимого постов, но не полной их омиссией. Это может быть недостаточно для ваших требований, так как посты продолжат отображаться в списках, просто не будут видны незарегистрированным пользователям. -
Метаданные постов и использование
pre_get_posts
:
Оптимальным решением будет использование метаданных для пометки постов, которые необходимо скрыть. Для этого можно применить хукpre_get_posts
, чтобы изменять запросы на выборку постов в зависимости от статуса пользователя.Пример кода, который скрывает посты с метаданными
hide_from_guests
, устанавливаемым на ‘true’:function wpse225120_hide_posts_from_guests( $query ) { if( is_user_logged_in() ) { return; // Если пользователь залогинен, ничего не меняем } // Получаем текущие метаданные $meta_query = $query->get( 'meta_query' ); // Создаем новый мета-запрос для фильтрации скрытых постов $hidden_meta_query = array( 'relation' => 'OR', array( 'key' => 'hide_from_guests', 'value' => 'false' ), array( 'key' => 'hide_from_guests', 'compare' => 'NOT EXISTS' ) ); if( ! is_array( $meta_query ) || empty( $meta_query ) ) { $query->set( 'meta_query', $hidden_meta_query ); return; } // Модификация существующего мета-запроса if( isset( $meta_query['relation'] ) && 'OR' === $meta_query['relation'] ) { $meta_query = array( 'relation' => 'AND', $meta_query ); } $meta_query[] = $hidden_meta_query; $query->set( 'meta_query', $meta_query ); } add_action( 'pre_get_posts', 'wpse225120_hide_posts_from_guests' );
Данная реализация работает таким образом, что если пользователь не авторизован, то выполняется запрос метаданных, отбирающий только те посты, которые не помечены как скрытые.
-
Изменение тем и адаптация кода:
Если вы хотите изменить видимость на уровне вывода постов в отдельных шаблонах, вам также следует учитывать изменения в темах, чтобы обеспечить четкость и последовательность. Использование функцииis_main_query()
позволит вам избежать непреднамеренного изменения всех запросов. -
Редиректы для незарегистрированных пользователей:
Также может иметь смысл сделать редирект для незарегистрированных пользователей на страницу регистрации или другую целевую страницу, если они попытаются получить доступ к защищенному контенту. Пример кода:function bp_logged_out_page_template_redirect() { if( ! is_user_logged_in() && ( is_page( 'members' ) || is_page( 'activity' ) || bp_is_user() ) ) { wp_redirect( home_url( '/register/' ) ); exit(); } } add_action( 'template_redirect', 'bp_logged_out_page_template_redirect' );
Этот код будет направлять незарегистрированных пользователей на страницу регистрации, если они пытаются получить доступ к страницам, которые должны быть защищены.
Рекомендации по реализации
-
Тестирование: После внесения изменений важно протестировать их на предмет корректной работы как для зарегистрированных, так и для незарегистрированных пользователей.
-
Производительность: Старайтесь минимизировать изменения в глобальных запросах, чтобы не влиять на производительность вашего сайта.
-
Документация: Не забывайте документировать ваши изменения, чтобы в будущем подобные задачи можно было выполнять легче и быстрее.
Заключение
Скрытие постов для незарегистрированных пользователей в WordPress — это задача, которую можно решить различными способами. Использование метаданных вместе с хуками pre_get_posts
и контролем за тем, какие пользователи видят контент, обеспечит необходимую гибкость и безопасность вашего сайта. Помните, важно, чтобы ваши решения не негативно сказывались на производительности и пользовательском опыте.