先日「ログインしたユーザーそれぞれ向けの投稿だけを表示するには?」というご相談を受けました。最近、カスタム投稿タイプを使って似たようなことは行ってきましたが、なかなか複雑でブログにも書いてはいませんでした。カスタマイズの内容を単純化すればブログに書く程度には収まるかな?と思いましたので「ログインしたユーザーだけがそのユーザー向けのコンテンツを見られる」という機能を実現するために何をすればできるか、についてまとめてみます。
最初に、ご注意!
この記事では多くの手順の作業を行います。また、すべての環境でのテストは不可能ですので環境によって不具合が起こる可能性もあります。ということでこのカスタマイズは「今ばりばりに使っているホームページ」ではなく「テスト用のホームページ」やローカル環境にあるホームページなどで、自己責任の範囲においてお試しください。
ログインユーザーそれぞれ向けのコンテンツだけを表示する、とは?
通常、見せるだけのWEBサイトをWordPressで作った場合はユーザーは書く側というか運営する側の管理者ユーザーしか作りません。
しかし、例えば「PC教室」を私がやっていたとして「複数人の生徒さん」がいる場合、「購読者」としてその生徒さんたちがログインできるようにしておいてログインした人だけが見ることのできる「生徒さんへのお知らせ」とかを作ったりすると使い勝手がいいという場合があります。
今回のカスタマイズはさらに1歩進めて「ログインした生徒さん別に知らせたい情報を見せることができるようにする」というものです。
イメージとしては、こんな感じのものです。
このようにするためにはどうしたらいいか?ということを考えました。
カスタム投稿タイプ:ログイン専用ページの仕様
とういことでこれを実現するためのカスタム投稿タイプを作って、その仕様も考えてみます。とりあえずブログに書けるように仕様はかなり簡略化してあります。
カスタム投稿タイプについて
カスタム投稿タイプ及びカスタムタクソノミーは以下を作ります。
カスタム投稿タイプ名:ユーザー専用ページ
post_type:luserpage
カスタムタクソノミー:ユーザーカテゴリー
スラッグ:lusercategory
ログインした人向けのコンテンツをどのように識別するか?については、カスタムタクソノミー(投稿で言うとカテゴリー)を作って、識別しようと思います。この方法は「購読者」として登録したユーザーをカスタムタクソノミーに追加する、という手作業が必要となります。
先ほどの図にあるように、ログインしているかどうかとログインしている人がどの権限グループに入っているかで表示内容が変わります。
未ログイン:一覧、詳細ページ共に見られない(トップページへ強制リダイレクト)
購読者:一覧、詳細ページは自分宛に作成されたものが見られる(他の人の詳細ページurlを入力するとトップページへリダイレクト)
管理者:一覧、詳細ページともにすべて見ることができる
実現させるために利用するプラグイン
これらを実現させるためにプラグインを使います。以下のプラグインをインストールして、有効化しておきます。
プラグイン名:Custom Post Type UI
目的:カスタム投稿タイプを作る
プラグイン名:Code Snippets
目的:カスタマイズコードを書くため
プラグイン名:show current template
目的:利用しているテンプレート名を知るため
※ テーマLightningの子テーマでカスタマイズする場合は入れなくても可(このブログでテンプレート名がわかるので)
子テーマを作っておく
このカスタマイズをするには独自テンプレートが必要となるため、現在適用されているテーマが子テーマではない場合は子テーマを作って、その子テーマを現在のWEBサイトで有効化しておきます。
子テーマにするにはという方法がわからない場合は、
これらのどちらかを参考に行って下さい。
今回はLightningの子テーマLightning-childというものが有効化されているという前提で説明します。
ユーザー専用ページのカスタマイズ方法
これでユーザー専用ページのカスタマイズ準備が終わりました。カスタマイズをしていきます。
カスタム投稿タイプ、カスタムタクソノミーを作る
カスタム投稿タイプを作ります。
ダッシュボード CPT UI>投稿タイプの追加と編集 をクリック
投稿タイプスラッグ:luserpage
複数形のラベル:ユーザー専用ページ
単数形のラベル:ユーザー専用ページ
と入力
このページの下の方にあるアーカイブあり を True にします。
一番下にある投稿タイプを追加をクリック。これでカスタム投稿タイプができました。
カスタムタクソノミーを作ります。
ダッシュボード CPT UI>タクソノミーの追加と編集 をクリック
タクソノミースラッグ:lusercategory
複数形のラベル:ユーザーカテゴリー
単数形のラベル:ユーザーカテゴリー
利用する投稿タイプ:ユーザー専用ページ にチェック
階層:True にチェックをする
タクソノミーの追加をクリック。これでカスタムタクソノミーが作成されました。
カスタム投稿タイプを追加したのでパーマリンクを更新しておきます。
ダッシュボード 設定>パーマリンク設定をクリック
表示されたページの一番下にある
変更を保存をクリックしておきます。
ユーザーカテゴリーにユーザーを追加する
ユーザー専用ページを機能させるには、ユーザーカテゴリーに購読者ユーザーを追加しておきます。
例えば、テスト用に 山田、田中 というユーザーを
ダッシュボード ユーザー>新規追加 から作っておきます。
このように元々ある管理者と追加された、購読者という権限グループのtanaka、yamadaというユーザーがあるという前提で説明を続けます。
ダッシュボード ユーザー専用ページ>ユーザーカテゴリーをクリック
名前には選択するときに分かりやすい名称を入れます。スラッグはユーザーのユーザー名を入れます。これを間違えると正しく動かないので注意して下さい。
2名分の追加をしました。
一覧表示、詳細表示用のテンプレートを子テーマに作る
一覧表示、詳細表示用のテンプレートを子テーマに作ります。今回はLightningを使うので、テンプレート名はわかっていますがそれ以外の場合は、追加したプラグインshow current templateを有効化してあれば、どのテンプレートを作ればいいかがわかります。
ブログの一覧ページを表示させたとき、管理者がログイン中であれば
このようにテンプレート名が表示されます(この場合はテンプレート名は index.phpです)
同じようにブログの詳細ページを表示させれば
このように、詳細ページは single.php をコピーすればいいことがわかります。
この一覧や詳細で使われているテンプレートはテーマによって大きく異なりますのでshow current templateを使って確認するようにして下さい。
今回はLightningの子テーマでのカスタマイズ方法を書きます。
Lightningからindex.phpを子テーマのフォルダ(lightning-child)にコピーして archive-luserpage.php とリネームします。同じく single.php をLightningから子テーマのフォルダ(lightning-child)にコピーして single-luserpage.php とリネームしておきます。
※ もしも子テーマのフォルダ(lightning-child)に既に同じ名前がある場合は、関係のない場所にペーストして、リネームしてから子テーマに入れます。
親テーマがLightningの場合の子テーマのフォルダ(lightning-child)にコピーした各ファイルのカスタマイズは以下の通りです
archive-luserpage.php
ID == 0){ wp_redirect( home_url() );exit; } ?>
<?php get_header(); ?> の前にphpコードを入力して、ログインしていなければトップページにリダイレクトさせます。
このほかユーザーで表示データを絞る部分については後から説明するCode Snippetsで実現します。
single-luserpage.php
ID == 0){ wp_redirect( home_url() );exit; } // 管理者以外は表示しようとしている投稿のタクソノミーにログインnameがないときは表示しない $category_name = 'lusercategory'; $user = wp_get_current_user(); // 管理者はOK if ($user->roles[0] == 'administrator') { } else { $terms = get_the_terms($post->ID, $category_name); $check = false; foreach($terms as $term){ // 表示しようとしている投稿のタクソノミーに今見ている人のlogin_nameと一致したものがあれば表示 if($term->slug == $user->user_login){ $check = true; break; } } if ($check == false){ wp_redirect( home_url() );exit; } } ?>
<?php get_header(); ?> の前に上記のphpコードを挿入します。ログインしていなければトップページにリダイレクトする。ログインしていて管理者以外の場合は、表示しようとするコンテンツのタクソノミーが見ようとしている人のユーザー名に一致したものがあるかどうかをチェックし、なければトップページにリダイレクトしています。
という記述部分を削除します。前ページ/次ページ の機能がある場合は、この部分の抽出も制御しないといけない(ユーザーによって異なる)のですが、複雑になりそうでしたのでとりあえず表示しないという方法にしました。
Lightningだけ?かもしれないカスタマイズ
また、Lightningの場合なのですが「カテゴリーが表示される」「ただし1つめだけ」という仕様になっています。ここを気にしなければ以下の2つのカスタマイズは必要ないのですが、例えば「山田」「田中」という2人用にコンテンツを作った場合でも、カテゴリーが「山田」と表示されるため、今回の「ユーザー専用ページ」のカスタマイズとしては少しまずいかなと思ったのでカスタマイズしています。管理者の時はカテゴリーを表示するけど、それ以外の時は表示しないということをしています。
以下の2ファイルをコピーしてリネームします。
Lightningからコピーするファイル→コピーしたファイルをリネームする
module_loop_post.php → module_loop_luserpage.php
module_loop_post_meta.php → module_loop_luserpage_meta.php
カスタマイズ部分は以下の通りです。
module_loop_luserpage.php
という行を
に書き換えます。
module_loop_luserpage_meta.php
元々ある
echo '
';
この部分を
$user = wp_get_current_user();
if ($user->roles[0] == 'administrator') {
echo '
';
}
このように書き換えることで、管理者の時以外にカテゴリー(タクソノミー)が表示されないようにしました。
テンプレートのダウンロード
Lightningの子テーマを使っている場合の4つのファイルは
こちらに置きました。色々な環境ではテストしていませんので、自己責任でよろしければダウンロードしてお試し下さい。
各種コードをCode Snippetsで設定する
今回なるべくテーマによる影響を少なくしたかったので、functions.phpに書いても動くのですがCode Snippetsにコードを入れてみました。
Code Snippetsの基本的な使い方は
こちら↑を参照して下さい。
管理者以外のログイン時各種制御
管理者以外のログイン時各種制御 という名前を付けて以下のコードを入れて保存します。
//管理者以外はログイン成功時、ダッシュボードではなくトップページへ飛ばす function redirect_login_front_page() { if( !current_user_can('administrator') ){ $home_url = site_url('', 'http'); wp_safe_redirect($home_url); exit(); } } add_action( 'wp_login', 'redirect_login_front_page' ); //管理者以外はアドミンバーを非表示 function my_function_admin_bar( $content ) { return ( current_user_can( 'edit_posts' ) ) ? $content : false; } add_filter( 'show_admin_bar', 'my_function_admin_bar' ); // 管理者以外はjetpack非表示にする add_action('jetpack_admin_menu', 'hide_jetpack'); function hide_jetpack() { if ( !current_user_can('level_10') ) { remove_menu_page( 'jetpack' ); } }
ログインユーザー専用ページ一覧のデータ抽出
ログインユーザー専用ページ一覧のデータ抽出 という名前を付けて以下のコードを入れて保存します。
function get_luserpage($query){ $category_name = 'lusercategory'; $user = wp_get_current_user(); if ( is_post_type_archive( 'luserpage' )) { if($query->is_main_query()){ if ($user->roles[0] == 'administrator') { } else { /* 管理者でないとき、その人のカテゴリーのみを表示 */ $taxquery = array( array( 'taxonomy' => $category_name, 'field' => 'slug', 'terms' => array( $user->user_login ) ) ); $query->set( 'tax_query' , $taxquery ); } } } } add_action( 'pre_get_posts', 'get_luserpage' );
ここでは一覧を取得するときに、管理者以外だったらログインしている人のユーザー名と同じタクソノミーしか取得しないというコードを書いています。
※ (2019/01/24追記)ユーザーがログインして一覧を表示したときにメニューが表示されない!という状況の報告をいただき if($query->is_main_query()){ 分岐を追加しました。
Be Geek様のpre_get_postsいじったらカスタムメニューが表示されなくなった話を参照させていただきました。ありがとうございます。
検索でカスタム投稿タイプの投稿を検索対象から除きます
検索でカスタム投稿タイプの投稿を検索対象から除きます という名前を付けて以下のコードを入れて保存します。
※ CPT UIでも指定ができるのですが、そこで指定をすると他の動きに影響が出てしまったためここで制御します
/** * 検索でカスタム投稿タイプの投稿を検索対象から除きます。 */ function search_exclude_custom_post_type( $query ) { if ( $query->is_search() && $query->is_main_query() && ! is_admin() ) { $query->set( 'post_type', array( 'post', 'page' ) ); } } add_filter( 'pre_get_posts', 'search_exclude_custom_post_type' );
上記では実際には検索対象から除くということではなく、指定したpost_typeのコンテンツのみを検索するコードになっています。post(投稿)、page(固定ページ)以外にも検索対象としたいコンテンツがあれば array の中に追加します。
ここで指定する3つのファイルをまとめてエクスポートしておきました。
こちら↑からダウンロードできます。解凍してインポートして、アクティベートすると利用できるようになります。ご利用は自己責任でお願いします。
ユーザー専用ページのデータを作る
ユーザー専用ページのデータを入力します。山田さん専用のコンテンツ、田中さん専用のコンテンツ、山田さんと田中さん用のコンテンツを作ってそれぞれ正しく表示されるかを確認します。
ダッシュボード ユーザー専用ページ>新規追加をクリック
タイトル、内容を入力したら
ユーザーカテゴリーで表示させたいユーザーの名前をクリックして、
公開します。これを繰り返して残りの田中さん専用のコンテンツ、山田さんと田中さん用のコンテンツを作り、合計3つのデータができあがります。
ユーザー専用ページの表示を確認する
カスタマイズが終わり、データも入りましたのでユーザー専用ページの表示を確認します。
一覧の表示
一覧の表示は ホームページのurl/luserpage/ で表示することができます。
管理者がログイン中に ユーザー専用ページ一覧を見ると
今入力したすべてのコンテンツが一覧されます。「おしらせ:年末年始について」は「yamada」「tanaka」のタクソノミーが指定されています。
yamadaというユーザー名を使ってログインして一覧を見ると
このように2件の表示になります。
tanakaでログインすると
このように2件の表示になります。
ログインしていない人がこのurlを表示させると、トップページにリダイレクトします。
このようにurlが同じ(ホームページのurl/luserpage/)でも見える内容が異なってきます。
詳細ページの表示
詳細ページは一覧のタイトルをクリックして表示できます。もしも「tanaka」でログインしたユーザーが何らかの形で「yamada」専用のの詳細ページurlを知った場合でも表示しようとしたときにテンプレートのphpコードにより、トップページにリダイレクトされます。
管理者はすべてのページを見ることができ、ログインしていない人はトップページにリダイレクトされます。
まとめ:長い、、、ですが順番にやればできるはず。
とてつもなく長くなってしまいました。Lightningではこんな感じのカスタマイズになります。テンプレートを使うカスタマイズの場合はどうしてもテーマによって方法が異なってしまいます。Lightning以外の方は「一覧表示、詳細表示用のテンプレートを子テーマに作る」で使う親テーマのテンプレートが違うかと思いますが、頭に挿入するphpコードは同じものでいけるはずですので試してみて下さい。くれぐれも万一壊れてもいい環境で、のお試しをお願いします。
また、今回とても長くなってしまったため「カテゴリー表示」のコントロールについて試したものがあるのですが掲載していません。カテゴリーを表示できるテーマの場合、権限がないコンテンツが表示される可能性はあります。Lightningについてはこの点についても問題ないようにカスタマイズをしてみて成功したのですが、テーマによってこのカスタマイズがかなり違う(必要なかったりもしそうです)ので誤解を招かないように割愛しました。もしかして後日気力がわいたらこの記事に追加して書くかもしれません。
コメント