サポート » 使い方全般 » サブメニューが属するメニュー名を取得したい

  • こんにちは

    ごく普通の階層構造のメニューを作った場合に、
    menu1
    sub1-1
    sub1-2

    menu2
    sub2-1
    sub2-2

    例えばsub2-2をクリックしてそのページが開いた時に、そのsub2-2が属しているメニュー名(menu2)を
    取得したいのですが、どうやれば良いでしょうか?
    要するに子要素あるいは孫要素から遡って最上位のメニューの名前を知りたいのです。

15件の返信を表示中 - 1 - 15件目 (全15件中)
  • こんにちわ。
    パンくずリストができるようなコードを記載しておきますね。
    なにかの足しになればよいのですが。


    <?php
    //現在の投稿情報を借り受け
    $posty = $post;
    //現在のタイトルを取得
    $me_title = get_the_title();
    //親記事IDを取得
    $parent_id = $posty->post_parent;
    //リストの変数宣言
    $breadtrail = "";
    //親IDがある限り循環
    do{
    //親ページのタイトル取得
    $parent_title = get_post($parent_id)->post_title;
    //親ページのリンクを取得
    $parent_link = get_post($parent_id)->guid;
    //自身の複製を防ぐためにタイトル確認
    //同じタイトルで階層をつくるのは「ありえない」(無意味)という見解から
    if(strtolower(trim(strip_tags($parent_title)))==strtolower(trim(strip_tags($me_title)))){
    //そういうニーズがあろうと終了
    break;
    }else{
    //タイトルが異なっていれば
    if(strlen($breadtrail)>0){
    //先にデータが入っていれば>付きで階層追加
    //変数に加算は 変数 = 加工データ+以前の変数 という形で成り立っています
    //(さかのぼって追加していくため)
    $breadtrail = "".$parent_title.""." > ".$breadtrail;
    }else{
    //データがまだなければそのまま代入
    $breadtrail = "".$parent_title."";
    }
    }
    //親ページを借り受けページにして親参照を確認
    $posty = get_post($parent_id);
    //いま借り受けた親ページの親を確認
    $parent_id = $posty->post_parent;
    }while($parent_id);
    //親がなければ終了
    //文字情報があれば表示
    if(strlen($breadtrail)>0){ echo $breadtrail." > ".$me_title; }
    ?>

    トピック投稿者 shinzanmono

    (@shinzanmono)

    msioさん
    情報ありがとうございました。
    私はWordPressやPHPの初心者なのですが、教えて頂いた情報は記事を遡ってパンくずリストを作成する手法ですね。
    とても参考になりました。
    最上位メニューの名前を取得する場合に、同じような手法が使えるのは分るのですが、具体的にどのようにPHPを書いたら良いのか分かりません。
    もう数時間試行錯誤していますが出来ません。
    困りました。

    使ったことはないのですが
    この関数でメニュー項目を取得すれば、親がどれか特定できるみたいです。
    http://wpdocs.osdn.jp/関数リファレンス/wp_get_nav_menu_items

    本家の Code Reference にサンプルコードが掲載されているので試してみてはいかがでしょう。
    https://developer.wordpress.org/reference/functions/wp_get_nav_menu_items/#comment-1800

    Get simple array of menu.

    function wp_get_menu_array($current_menu) {
        ...     
    }
    
    CG

    (@du-bist-der-lenz)

    階層構造のメニューという考え方から外れて、移動した先のページでメニューを条件分岐させるということで出来るでしょう。

    is_front_page()でフロントページでのみ、「Vintage LPs」を表示させてみました。

    is_front_page()

    フロントページ以外では『ショップ』と入れ替わります。

    http://store.amadeusclassics.com/classical/product-category/vintage-vinyl/

    私の拙い進言でお困りを深めてしまって申し訳有りません。
    パンくずをつくるにあたり自分から順に親を取得していけば最後は親にたどりつくので、積み上がって行く途中経過を破棄すれば、最後の値が元の親として示せるのではないかと思った次第でした。
    なので、親があれば「追加」ではなく「変数を上書き」して終了すれば最後に残ったものが親になるのではないかと思いましたものでご迷惑をおかけいたしました。
    つい、遡るといえばいずれパンくずの必要性がでてくるのではと思い行きすぎたまねをしました。

    どのようにというご要望について分かりかねる程度の推察でもうしわけないのですが、ドットで変数を繋げると追加になるので、イコールで上書きして最後の値を取得するコードに変更して、使い方としてはテンプレートに直接書き込むと使えるとおもうのですがいかがでしょうか。

    page.php などのテンプレートにそのままはりつけ、echoの部分だけ任意の箇所にはりつければ出力はそのechoの部分からされるのですがお試しいただければ幸いです。

    @msio さん、管理画面の 外観 > メニュー で作ったナビゲーションメニューの場合、固定ページではない外部URLなどもメニューには入れられますよね。
    そのため、親メニュー項目は固定ページの親ページ(投稿オブジェクトの post_parent)ではありません。
    wp_get_nav_menu_items() で取得できるメニュー項目オブジェクトの menu_item_parent が親メニュー項目(の ID)です。

    すみませんでした。
    単純な階層構造がページの親子関係だと勘違いをしておりました。

    もう解決されたでしょうか。
    他の方々がご指摘されているとおり、私の完全な間違いであり恥の上塗りではありますが他の方々がご紹介されている内容についていまさら同じことの繰り返しになりますが表記させていただきます。
    なにとどご容赦いただけると幸いです。

    
    <?php
    //抽出パラメータ
    //逆順で一番上の親が先頭
    $param = array(
            'order'                  => 'DESC',
            'orderby'                => 'menu_order',
            'post_type'              => 'nav_menu_item',
            'post_status'            => 'publish',
            'output'                 => ARRAY_A,
            'output_key'             => 'menu_order',
            'nopaging'               => true,
            'update_post_term_cache' => false );
    //親ノードストリーム取得
    $famtree = wp_get_nav_menu_items( 'sample_menu', $param );
    //一番目のアイテムが総本家なのでリンク作成
    $parent_text = "<a href=\"".$famtree[0]->url."\">".$famtree[0]->title."</a>";
    //作成したリンクを表示
    echo $parent_text;
    //パンくず変数
    $breadtrail = "";
    //末端まで循環
    foreach($famtree as $value_fam){
    	//変数に既値あればセパレータ追加
    	if(strlen($breadtrail)>0){ $breadtrail .= " > "; }
    	//リンクを追加
    	$breadtrail .= "<a href=\"".$value_fam->url."\">".$value_fam->title."</a>";
    }
    //親たちのリンクに自分の名前を任意で追加し表示
    //get_title でいいと思いますが
    echo $breadtrail." > and me";
    ?>
    
    • この返信は7年、 1ヶ月前にmsioが編集しました。理由: コードの記述(リンク)埋め込みがタグ変化していたのであらためて再投
    トピック投稿者 shinzanmono

    (@shinzanmono)

    msioさん
    わざわざサンプルプログラムを作って頂きまして有難うございました。
    PHP初心者の私には非常に参考になります。
    ただ、このプログラムですと、全部のメニュー項目が一行に連結できますが、

    menu1 > sub1-1 > sub1-2 > menu2 > sub2-1 > sub2-2 > and me

    もともとの質問に有るように、例えば
    sub2-2 をクリックして表示する時に、その最上位の項目
    menu2 を取得するように応用が出来ませんでした。
    PHPの勉強も兼ねて、もう少し試してみます。
    いずれにしまして、大変ありがとうございます。

    十重二十重ご迷惑をおかけし申し訳ございません。
    menu がメニュー単位で sample_menu に検索対象メニュータイトルを入れていただければ
    調査が可能、0番目がトップレベルだとおもっていたのですが
    menu は作成されたメニューのトップレベルで複数あるということですよね。

    自分の属する、を探すのであればin_arrayで自身を配列から検索し
    含まれていればその階層の最上位を取得する、という動作が望ましいということでしょうか。

    メニュータイトル>customized_menu—内↓
    menu1 top level

    ├SUB1
    └SUB2

    menu2 top level ← これを取得したい

    ├SUB1
    └SUB2 Current★
    メニュータイトル>customized_menu—迄↑

    ちょっと私の実力では力及ばずというところだと思いますがなにかできることがありましたら頑張りたいと思います。

    こんにちは

    wp_get_nav_menu_itemsで取得したメニューを再帰的に親を検索するのが定石な気がしますが・・・

    以下は、粗削りであんまり良くないソースな気もしますが、とにかく動いたので参考までに載せておきます。
    自分自身のタイトルがメニューという前提などもあり、そのままでは動かないのではと思います。
    get_menu_top関数を再帰的に呼び出しています。

    $menu_items = wp_get_nav_menu_items( 4 );    //メニューを取得
    $item       = array_values( array_filter( $menu_items, 'menu_filter' ) )[0];    // メニューから自分自身のアイテムを取得
    
    $items = set_items( $menu_items );    // メニューを検索しやすいように整形
    $top   = get_menu_top( $item );    // トップレベルのアイテムを取得
    
    /** メニューから自分自身のリンク元アイテムを取得する */
    function menu_filter( $var ) {
    	global $post;
    
    	return $var->post_title == $post->title;    // メニューのタイトルが遷移先画面(投稿や固定ページ)のタイトルと同じという想定です
    }
    
    /** 親メニューを取得しやすいように整形する */
    function set_items( $menu_items ) {
    	$items = array();
    	foreach ( $menu_items as $item ) {
    		$items[ $item->ID ] = $item;
    	}
    
    	return $items;
    }
    
    /** 自分自身の最上位メニューを取得する */
    function get_menu_top( $item ) {
    	global $items;
    	if($item->menu_item_parent !== '0'){
    		return get_menu_top($items[$item->menu_item_parent]);
    	}else{
    		return $item;
    	}
    }
    • この返信は7年、 1ヶ月前にmunyaguが編集しました。

    なにもかも良い結果に至らず大変申し訳ございませんでした。
    最後に呈しました構造の要件を満たすと思われる例を掲示いたします。
    今回は作業のお邪魔ばかりしてしまいましたがいずれなにかのお力になれますよう努力いたします。

    <?php
    //抽出パラメータ
    $param = array(
            'order'                  => 'DESC',
            'post_status'            => 'publish',
            'nopaging'               => true,
            'update_post_term_cache' => false );
    //親ノードストリーム取得
    //customized_menu = 作成メニュー名サンプル
    $famtree = wp_get_nav_menu_items('customized_menu', $param );
    //自ノード格納変数 配列型
    //変数は宣言しておくのがセオリーですが
    //自ノード確定できなかったときに中断する要素にするため
    //宣言せず抽出されたときにフラグを兼ねるため宣言せず
    //$MyObject = array();
    //抽出されたメニューデータを循環
    foreach($famtree as $value_fam){
    	//自分のIDとメニューのIDが合致すれば確保
    	if($value_fam->object_id==get_the_ID()){
    		//自ノードの確定
    		$MyObject = array(
    						"title" => $value_fam->title,
    						"url" =>  $value_fam->url,
    						"object_id" =>  $value_fam->object_id,
    						"db_id" =>  $value_fam->db_id,
    						"parent" =>  $value_fam->menu_item_parent,
    						);
    		//自ノード確保循環終了
    		break;
    	}
    }
    //自ノードが確保されていたら(メニューの要素だったとき)
    if($MyObject){
    //親ノードを持たなくなるまで円環
    do{
    	//懲りずにメニュー要素を循環
    	foreach($famtree as $value_fam){
    		//親ノードを発見したら
    		if($value_fam->db_id==$MyObject["parent"]){
    			//親ノードを自ノードとして確定 自己吸収
    			$MyObject = array(
    							"title" => $value_fam->title,
    							"url" =>  $value_fam->url,
    							"object_id" =>  $value_fam->object_id,
    							"db_id" =>  $value_fam->db_id,
    							"parent" =>  $value_fam->menu_item_parent,
    							"child" => $MyObject,
    							);
    		}
    	}
    }while($MyObject["parent"]>0);
    //自称「自ノード」が完了するまでループ
    //自ノードを食ってのぼり配列の先頭が総本家です
    //総本家からchild要素がなくなるまで参照すると
    //末端までパンくずができます。
    }
    //変数の状況をテスト出力
    var_dump($MyObject);
    ?>
    
    トピック投稿者 shinzanmono

    (@shinzanmono)

    munyaguさん
    サンプルプログラムありがとうございました。
    大変参考になりましたが、PHP初心者の私にはそのままでは動かせませんでした。
    動くように少し修正もしてみましたが、動かせませんでした。

    msioさん
    度々お世話になっております。
    サンプルプログラムを実行したところ期待通りの結果が得られました。
    大変ありがとうございます。
    処理の流れはどうにか理解できたのですが、勉強も兼ねて今必死で解読中です。
    なお、例えば
    menu1
    sub1-1
    sub1-2 <== もしこれと同じ名前のメニューが

    menu2
    sub2-1
    sub1-2 <== ここにもあると、

    二カ所にあるどちらの sub1-2 をクリックしても、それに応じて
    menu1 や menu2 が取得できるのではなくて、毎回 menu1 が取得されるようです。
    メニューの中に同じ名前の項目を入れる状況は殆どないので実用上は全く問題有りませんが。
    でも、なぜそうなるのかは私には分かりません。
    もし理由が分かりましたら参考までにお教え頂けるとありがたいです。
    いずれにしましても、大変ありがとうございました。

    大変申し訳ございません。
    私の力量不足のせいで、それはなんとするもかなわない事項です。

    誠に身勝手な申し出なのですが、経路の異なる到着点を同列に配置する方向で機能をつけるならば
    ページ遷移を記録して元を表示するような機能のほうが理想的かと思います。
    親ページでタイトルを取得し、その情報を子経路内では維持・表示するというほうがよいと思うのです。

    なぜならば、そのページを経路なしに読み出した場合と経路をたどって読み出す場合の可能性は
    半々として、二個の経路があるとするなら、実質的に親子関係の意味をなさない状況が半分あるということに
    ならないでしょうか。

    二つのメニューがあって、半分が機能しない状況が想定されるということは、一つでよいのではないでしょうか。

    小説の分岐のように、経路によって同じ項目を踏む、経路が別という局面も想定されるかと思うのですが
    小説も読み進める視点単位は1つで、2経路同時に進行はせず、二冊を同時によみすすめて同じページに至る
    ことがないように、必要性についてすこし疑問に思うところがあります。

    データの形質についてばかり重視する話で辟易とされるかと思うのですが、ワードプレスは構造効率化が非常によいと思って
    おりますので、お時間のある際にご参考いただけると幸いです。

    トピック投稿者 shinzanmono

    (@shinzanmono)

    msioさん
    詳しい解説ありがとうございました。
    WordPressやPHP初心者の私にはまだ良く理解出来ませんが、解説文を何度も読み返して理解したいと思います。

15件の返信を表示中 - 1 - 15件目 (全15件中)
  • トピック「サブメニューが属するメニュー名を取得したい」には新たに返信することはできません。