サポート » 使い方全般 » 選択ページの一番上の親のID取得方法

  • 解決済 goodtimes

    (@goodtimes)


    こんにちは お世話になります

    選択されているページの、一番上の階層のIDを取得するにはどうしたらいいのでしょうか?(直前の親ではなく、一番の親です)
    ちなみに使用テーマはkuburicのデフォルトです

    <?php echo get_the_title($post->post_parent); ?>
    過去記事により、上記のように記述すると、直前の親のタイトルが取れることはわかりました。

    具体的になにがしたいかというと

    A
    >AA
    >>AAA
    B
    >BB
    >>BBB

    という階層でページを作ってます
    で、AとBはナビボタンとしてヘッダーに配置しました

    サイドバーは何も触ってないので、上の階層のまま全部表示されています
    そして、本来このサイドバーには、以下のように表示したいのです

    1、選択されている一番の親(AもしくはB)を判断して
    2、選択されている子供のページたち(AならAA,AAAのみ)を表示したい

    よって、sidebar.phpのページ一覧表示のところに

    1.今現在表示している記事?ページ?のIDを取得
    2.取得したIDの一番上の親IDを取得(一番上の親が表示されていた場合は自分のIDが返ってくる?)
    3.wp_list_pagesでなんとか一番上の親を省いて(さらにX階層以降は省く)というふうにして子リストを階層表示

    とすればできる・・かな・・??と思っています

    一番上の親ページID取得方法のご教示、考え方のご指摘などいただけませんでしょうか?
    よろしくお願いします

9件の返信を表示中 - 1 - 9件目 (全9件中)
  • モデレーター jim912

    (@jim912)

    goodtimesさん、こんにちは。

    最上位のページは、post_parentが0になります。
    つまり、最上位のページを取得するには、post_parentが0になるまで、親ページを辿っていく手法が考えられます。

    実装方法ですが、post_parentが0であれば、現在のページを返し、そうでなければ自関数を再帰的に呼び出すユーザー関数を定義するのがよいかと思います。

    コードとしては、下記の通りとなります。
    記述箇所は、テーマのfunctions.phpあたりに追加するのが簡易かと思います。

    function ps_get_root_page( $cur_post, $cnt = 0 ) {
    	if ( $cnt > 100 ) { return false; }
    	$cnt++;
    	if ( $cur_post->post_parent == 0 ) {
    		$root_page = $cur_post;
    	} else {
    		$root_page = ps_get_root_page( get_post( $cur_post->post_parent ), $cnt );
    	}
    	return $root_page;
    }

    次に利用したいテンプレートで、

    if ( is_page() ) {
    	$root_page = ps_get_root_page( $post );
    }

    とすると、

    • ページ以外の場合
    • 階層が100を超えた場合

    以外に、$root_pageに最上位のページオブジェクトが返ってきますので、ID最上位ページのIDは、

    $root_page->ID

    で取得できるかと思います。

    サイドバーでの表示方法は、記述されている通りですので、あとはご自分で実装してみてください。($root_pageが返ってこない場合の処理もお忘れなきよう。)

    jim912さんが既にお答えになっていますが。

    K2 themeのサイドバーにご希望の機能を実現するコードがあります。
    Wordpress 2.5 以降で自動保存されたデータまで表示されるので若干修正して使っています。

    <?php
    /* Menu for subpages of current page (copied from K2 theme) modified by inazumatv.com */
    global $notfound;
    if (is_page() and ($notfound != ‘1’)) {
    $current_page = $post->ID;
    while($current_page) {
    $page_query = $wpdb->get_row(“SELECT ID, post_title, post_status, post_parent FROM $wpdb->posts WHERE ID = ‘$current_page'”);
    $current_page = $page_query->post_parent;
    }
    $parent_id = $page_query->ID;
    $parent_title = $page_query->post_title;

    // if ($wpdb->get_results(“SELECT * FROM $wpdb->posts WHERE post_parent = ‘$parent_id’ AND post_status != ‘attachment'”)) {
    if ($wpdb->get_results(“SELECT * FROM $wpdb->posts WHERE post_parent = ‘$parent_id’ AND post_status = ‘publish'”)) {
    ?>

    <li>
    <h2 class=”sidebartitle”>‘><?php echo $parent_title; ?> <?php _e(‘タイトル’); ?></h2>
    <ul class=”list-page”>
    <?php wp_list_pages(‘title_li=&child_of=’. $parent_id); ?>
    <ul/>
    </li>

    <?php } } ?>

    多分これで大丈夫ではないかと思います。
    ただ2階層まででしか使用したことがありません。

    ご希望のように3階層まで対応できるかは分かりません。

    もしお使いになるならK2 themeのクレジットは必ず入れてください。

    タグがうまく入力できないので一部全角になっています。

    WP2.5 以降であれば、 get_post_ancestors() が使えます。
    ページの ID を渡すと、親ページの ID を近い順の配列で返します。

    例えばそのページが特定のページの子ページであるかどうかを判断したいなら

    <?php if ( in_array( $targetID, get_post_ancestors( $post->ID ) ) ) : ?>
    このページは <?php echo get_the_title( $targetID ); ?> の子ページです。
    <?php endif; ?>

    記事の修正が何故か出来なくなっているので追記で訂正です。

    上の例の get_the_title() に echo が抜けていました。すみません。
    それと書き漏らしですが、もし get_post_ancestors() で最初の親ページの ID を取得される場合は

    $ancestor  = array_pop( get_post_ancestors( $post->ID ) );

    など配列の最後の要素を取り出せばいいと思います。

    # 追記:あれ、編集出来てますね。フォーラムのデータベースサーバーが複数あって同期がとれていないのかな? 今のところ私の環境では読み込むたびに表示される内容が違うので、私の書き込みのつじつまが合っていないかもしれませんがご容赦ください:-p

    get_post_ancestors
    先祖を取得、なるほど勉強になりました。

    $post->ancestors
    てのもあったんですね。

    トピック投稿者 goodtimes

    (@goodtimes)

    jim912さん、taikikenさん、mizubeさん、こんばんは
    ご回答ありがとうございます

    jimさんとmizubeさんがご提示くださった方法をやってみました
    taikikenさんがご教示くださったテーマはK2 themeのクレジット?を入れないといけない+今の私には読解が難しくて手を付けれていません… すみません

    ====
    で、jim912さんとmizubeさんの方法は、文章の中でなにをしているか理解&推測できました
    できたんですが、いざ実践すると階層がまったく表示されません
    画面上にエラー文章は出てません

    どちらの方法でも、最上位の親IDは取得できました
    echoで取得したIDの表示確認もしました

    ************************************************************
    <?php wp_list_pages('depth=5&child_of=$ancestor&title_li=<h2>' . __('Pages', 'kubrick') . '</h2>' ); ?>
    ************************************************************

    肝心な階層表示の文章(sidebar.php)がこれなんですが、、、
    なにがおかしいんでしょうか・・?
    表示されないということは、文章にエラーがあるからムシしているということですよね?
    (Jimさんのときは Jimさんが教えてくださった変数名にしています)

    ちなみに、child_of=34など手動で数字を入れると表示されます

    別件で2点質問です
    ・ 上記の関数?で、そもそも ‘ はなにを意味しますか?
    ・ mizubeさんが教えてくださったget_post_ancestors(素敵な名前ですね!)は
    どういうところに載っているんでしょう?
    codeXのタグ一覧?などを見たのですが見つけられませんでした

    よろしくお願いします

    ::::::::::::::::::::
    ::::::::追記:::::::::
    ::::::::::::::::::::
    逆クォートで囲ったんですが、うまく枠つきで表示されないので、目立つようにしました
    読みにくかったらすみません

    ::::::::::::::::::::
    ::::::::追記:::::::::
    ::::::::::::::::::::
    すみません書き忘れです
    mizubeさんの教えてくださった
    ************************************************************
    <?php in_array( $targetID, get_post_ancestors($post->ID )) ; ?>
    this page is the child of…<?php echo get_the_title($targetID); ?>
    ************************************************************
    を実践すると(日本語がなんか化けるんで、英語でしてます)、表示される$targetIDの中身は
    選択されているページの名前(親ではなく本人)が出ます
    これもなぜでしょうか・・?
    (get_post_ancestors($post->ID)で、現在選択されているページIDの先祖たちを$targetIDにいれてる、と理解してますが、あってますか?)

    get_post_ancestors(素敵な名前ですね!)はどういうところに載っているんでしょう?

    wp-includes/post.php にあります。

    シングルクォートの意味については PHP のマニュアル等をお読みになるべきですね。シングルクォート内では変数が展開されませんので . でつないでやる必要があります。そのためにそのような形になっています。

    ですから wp_list_pages() の引数に渡している $ancestor も

    <?php wp_list_pages(‘depth=5&child_of=$ancestor&title_li=<h2>’ . __(‘Pages’, ‘kubrick’) . ‘</h2>’ ); ?>

    ではなく

    <?php wp_list_pages('depth=5&child_of=' . $ancestor . '&title_li=<h2>' . __('Pages', 'kubrick') . '</h2>' ); ?>

    のように ‘文字列’ の外に変数を出してあげなければ展開されません。

    ************************************************************
    <?php in_array( $targetID, get_post_ancestors($post->ID )) ; ?>
    this page is the child of…<?php echo get_the_title($targetID); ?>
    ************************************************************
    を実践すると(日本語がなんか化けるんで、英語でしてます)、表示される$targetIDの中身は
    選択されているページの名前(親ではなく本人)が出ます
    これもなぜでしょうか・・?

    私の例とはコードが違いますよ^^; 見比べてみてください。

    in_array() 関数は配列の中に値があるかチェックする PHP 関数なので、 get_post_ancestors() の返す配列の中に $targetID が含まれているかを true か false で返しています。 in_array() によって $targetID に get_post_ancestors() の結果を入れているわけではありません。

    この場合 $targetID の値は空なので get_the_title() には ID が何も渡されていません。そこで get_the_title() は初期値の $post->ID を取得して投稿の名前を出力しているために、結果として表示中のページの名前が表示されるわけです。

    # 同じ経験があるのですが、色分けは、バッククォートの前後を改行するとうまくいくみたいですよ。

    トピック投稿者 goodtimes

    (@goodtimes)

    mizubeさんおはようございます

    丁寧なご回答ありがとうございます
    なるほどなるほどです!
    変数を文字列の外にだしてやったら(’のなぞはかなり多くのことを解決してくれました。wordpressではなく、PHPを先に勉強します)選択している親子の階層表示が現れました!

    ちょっと急ぎの別件をやることになって、教えてくださったこと(in array のifが抜けてたこととか)すべて理解&実践できていませんが、(別件も理解&実践も)長くなりそうなので、さきにお礼まで
    ここはまだ未解決のままにさせてください

    自力で最初の投稿で質問したことがすべて解決すれば、改めて解決済みにいたします
    といってもまた来ると思いますが・・その際はまたご指導いただければうれしいです

    トピック投稿者 goodtimes

    (@goodtimes)

    こんばんは

    皆さんが教えてくださって、無事、

    ・選択されているページの最上位を取得
    ・サイドバーに、選択している最上位より下(最上位含まない)子供一覧表示

    ができました!
    ありがとうございます!

    同じことをやりたい方がもしいらっしゃったときのために書いておきます
    (完全じゃないと思うので、ご注意です)

    <!– ページ表示は5階層まで –>
    <!– 選択ページの最上位$ancestorを取得 –>
    <?php $ancestor = array_pop(get_post_ancestors($post->ID)); ?>
    <?php if(empty($ancestor)) { /*選択ページが最上位*/
          wp_list_pages(‘depth=5&child_of=’ . $post->ID . ‘&title_li=<h2>’ . __(‘Pages’, ‘kubrick’) . ‘</h2>’ );}
    else { /*選択ページが最上位以外*/
          wp_list_pages(‘depth=5&child_of=’ . $ancestor . ‘&title_li=<h2>’ . __(‘Pages’, ‘kubrick’) . ‘</h2>’ ); }?>

    ********
    mizubeさん
    ********
    in_arrayがなにをする関数か、$targetIDがなぜ空で、選択ページの名前がでてくるのか(当然でしたね・・)理解できました
    ありがとうございます!

9件の返信を表示中 - 1 - 9件目 (全9件中)
  • トピック「選択ページの一番上の親のID取得方法」には新たに返信することはできません。