WordPressでパスワード保護した投稿は、通常の記事一覧にもタイトルが表示されてしまいます。この記事では、ログインしていない訪問者の記事一覧からだけパスワード保護された投稿を非表示にする方法を解説します。
この記事でわかること
pre_get_posts+has_passwordで一覧から除外する方法is_singular()の除外を忘れると起きる致命的な副作用
functions.phpにコードを追加する
テーマの functions.php に以下のコードを追加します。
functions.php:一覧からのみパスワード保護投稿を除外
function exclude_protected_posts( $query ) {
if ( is_admin() || ! $query->is_main_query() ) {
return;
}
// 一覧・アーカイブページのみが対象。個別ページ(is_singular)は除外しない
if ( $query->is_singular() ) {
return;
}
if ( ! is_user_logged_in() ) {
$query->set( 'has_password', false );
}
}
add_action( 'pre_get_posts', 'exclude_protected_posts' );
is_singular()を除外しないと記事自身が404になる
is_admin() と is_main_query() のチェックだけでは不十分です。この2つだけの条件で has_password => false を適用すると、パスワード保護された投稿自身の個別ページに直接アクセスしたときのメインクエリにも適用されてしまいます。そうなると「対象の投稿」×「パスワードが無い」という条件が同時に成立せず、WordPressはその投稿を見つけられずに404を返します。本来、パスワード保護は「知っている人がパスワードを入力すれば読める」仕組みのはずが、これでは誰にとってもアクセス不能になってしまいます。is_singular() の場合は必ず処理をスキップし、個別ページの動作に影響しないようにしてください。動作確認のポイント
- ログインしていない状態で記事一覧・アーカイブページを開き、パスワード保護された投稿が表示されないこと
- パスワード保護された投稿のURLに直接アクセスし、通常どおり「パスワードを入力してください」フォームが表示されること(ここが404になっていたら
is_singular()の除外漏れです) - ログイン済みの状態では、一覧にもパスワード保護された投稿が表示されること
関連するパスワード保護・一覧除外の実装
よくある質問(FAQ)
Qパスワード保護された記事をループでログインユーザーのみ表示するには?
A
is_user_logged_in()でログイン確認し、post_password_required()でパスワード要求チェックをして表示を切り替えます。post_password_required($post)は、その投稿がパスワード保護されていてまだ認証されていない場合にtrueを返します。Qpost_password_required()関数の使い方を教えてください
Aループ内で
if ( ! post_password_required() ) { ... }のように使うと、パスワード未認証の投稿だけ表示・非表示を切り替えられます。pre_get_postsでクエリ自体から除外する今回の方法とは異なり、ループ内で個別に判定したい場合に使います。Qパスワード保護記事の一覧でタイトルのみ表示してコンテンツは隠す方法は?
A
post_password_required()がtrueの場合は「パスワードで保護されています」などのメッセージを表示し、falseの場合はthe_content()で本文を表示します。get_the_excerpt()はWordPress側でパスワード保護時に自動的に保護メッセージを返します。まとめ
- 基本:
pre_get_posts+has_password => false - 必須:
is_singular()の場合は処理をスキップする - 確認:保護記事自身のページで通常どおりパスワード入力フォームが出ること
「一覧からは隠すが、直接アクセスした人はパスワードで読める」という本来のパスワード保護の趣旨を壊さないよう、影響範囲を一覧・アーカイブページに限定してください。

