wp_nav_menu のフィルターフック と
Page No.1
Contents
またしてもいまさらの、という感じで wp_nav_menu のいくつかのフックに関して。そして久々の WordPress ネタとなる。
まぁ、自分のサイトということであれば、php というか html で直接書いてしまったほうが、よほど手間もかからないし、サイトの表示の速さという点でもアドバンテージがあると思われる。
しかし、それが他の人たち用の WP となると全く話が違ってくる。html の知識のない人たちにとっては、編集するのにとっつきやすい、この wp_nav_menu や block editor はとても有用なものなのだろう。
と、いうことで自分としては久々の wp_nav_menu と付き合うこととなる。
まぁ、ひさしぶりに触ってみたけれど、これはそんなに変わっていないのかな!という印象。そしてこれも相変わらずなんだけれど、鬱陶しいほどの class が付いてくる。ほとんど使い道のないものばかりのように思えるのだけれど、果たしてこれだけの class をつけることに意味があるのだろうか!
まずは、その辺りの整理ができないものかということで、フックを探してソースコードを漁ってみる。
wp_nav_menu のある wp-includes/nav-menu-template.php にもいくつかフックがあるけれど、もっと直接的にいじれるものはないのだろうかと、wp-includes/class-walker-nav-menu.php の方も探してみると、こちらの方に目的に沿うであろうフックを見つけることができた。
nav_menu_css_class filter-hook
まずは、これ、nav_menu_css_class というフィルターフック。
このフックは、「Starts the element output.」の説明のついている、function start_el () の中にある。
得られる引数の $classes は、説明にあるように、適用されるべき class の文字列が入っている配列とのこと。なるほどっと、その配列をいじればいかようにでも出来るってことのよう。
その他の引数は、その menu item の様々な情報が入っているので、それによって分別して処理が行える。ここで言う menu item というのは、個々のリンクのことである。anchor タグにされて、class を設定され、li タグにてラップされる、その一つ一つのリンクの要素のこと。引数 $menu_item で得られる内容を見てみると、その項目が投稿で得られる情報と同じようなので、データベースを覗いてみると、wp_posts テーブルに投稿と同じように保存されていた。この場合の post_type は “nav_menu_item” である。
menu_item である個々のリンク要素を、投稿と同じようにデータベースに保存しているのにちょっと驚いたが、はて、それらをまとめて一つの navi menu にするのはどうするのだろうか、とテーブルを漁ってみると、term を使ってそれぞれ個々の menu_item と紐付けているのがわかった。navi menu を新規作成するときにつけたメニュー名は、wp_terms テーブルの name に見つけることが出来る。
と、いうことで、この $menu_item という引数から得られるのは、個々のリンク要素としての情報で、例えばそのリンクのラベルの文字列 ( post_title ) だとか、本来のリンクの url とか slug ( post_name ) とか、保存した月日とかである。
一方、それに対して $args の方はといえば、こちらは taxonomy としての情報となり、 navi menu としてのメニュー名だとか、menu を設定するときに必要な theme_location とか、wp_nav_menu() に設定した引数の値などを得ることが出来る。$args で得られる メニュー名によって、いま処理されている menu item がどの navi menu に属しているリンクかを判別出来るということである。
そして、$depth は入れ子になったリストの階層のレベルを知ることが出来る。一段目が 0。一つ下の階層が 1、2つ下が 2、という具合に数値で返してくれる。
それでは、実際のコード。
例えばそのサイトは日本語、英語、中国語の三ヶ国表示が必要で、メニューもそれぞれ用にと三種類を用意しているとして、Home へのリンクは特別にそれ用の class を付け、階層の深いリストは一段目と区別するための class を付ける。それ以外は不必要なので class は必要なし、ということならこんな具合。
nav_menu_link_attributes filter-hook
このフックも、nav_menu_css_class と同じ関数内にあり、すぐ後に続くように書いてある。
こちらは、リンクの機能となるアンカータグの、href、title、target、rel、aria-current、といった属性を設定できる。アンカータグ専用。
引数の $atts でそれらの属性値を渡してくれるのであるけれど、これはそれらの属性名を key とした連想配列になっている。で、その後の foreach によって、属性名であるキーと値を文字列として連結させて html 文を作っているだけのことなので、”id” なども設定できるのではと思いつつ試してみると、もちろん、それも可能だった。”id” だけでなくたとえば “data-****”とか、”style” も同じことなので、特にスタイルを設定したい特別なリンクがあれば、specificity score が1000 point の強力なインラインスタイルで設定できる。
その他の引数は、nav_menu_css_class フックと全く同じ。
サイトの navi menu において、あるページにおいての html アンカーというのかページアンカーというのは必ずと言ってよいほど使っていると思う。その場合、ページ内の対象の箇所の要素の id属性に#を付けてリンクに付加すればいいだけのことなんだけれど、wp_nav_menu の標準的機能においてはどうにもできないようである。その場合、このフックを使えば出来るということになる。であるからして、このフックは必須であり、とても重要なフックなのである。
と、いうことで、以下となる。
やっていることは、その htmlアンカーと言語指定用のクエリーを付加すること。スタイルを設定しやすいので、”id” 属性をそれぞれのアンカータグに設定し、アンカータグには title 属性があったほうが良いと思うので、それもくっつける、と。
nav_menu_item_id filter-hook
続いては、nav_menu_item_id フック。
これも同じ関数内で、nav_menu_css_class と nav_menu_link_attributes に挟まれたところにある。
リンクのアンカータグをラップする li タグにつく “id” 用のフィルター。
引数は “id” のデフォルトの文字列と、これも先の2つのフックと全く同じ三つで、もうすっかりおなじみとなった $menu_item、$args、$depth。
まぁ、これに関しては、”id” はデフォルトですでに設定されているし、何かしら特別な理由がない限り変更する必要もなさそうなので、あまり使うことはないのかもしれない。スタイル設定をどこかで使っていたものを使いまわしていたりして、それに “id” を合わせたいとかそういった事だろうか。と、いいつつ、自分の場合はもろにそのパターンなので、このフックにもしっかりお世話になっている。
nav_menu_submenu_css_class
このフックは、今までのものとは違う関数内にある。「Starts the list before the elements are added.」という説明書きの付いた function start_lvl() である。これは各リストの ul タグを生成する関数であり、このフックはその過程において ul タグの class を設定できる。デフォルトの class は”sub-menu” であり、それを変更したければこれを使うべし、ってところ。
この関数を見る限りにおいては、設定できるのは class 属性だけであり、id などは付加できないよう。引数の方は、デフォルトの “sub-menu” が一つだけ入っている $classed という配列と、おなじみの、$args、$depth である。ul タグは直接的にリンクアイテムを内包しないし、menu item とは一対一対応ではないので、$menu_item はあてがいようがない。
実にシンプルであり、変更、または追加したい class の文字列を、$classes の配列に入れて返すだけのことである。
今製作中のサイトでは、サイトマップも wp_nav_menu() で生成するようにしたが、サイトマップの場合は階層が深くなっているので、その階層によって識別できるように class を設定している。
その他にも、リンクのタイトルを変更できるフックなどもある。
なんだかんだと言いつつ、色々やっていればそれなりに思っているものに近いものになっている。この自由度の高さが WordPress の一番好きなところだったのだけれど、それが Gutenberg といえば・・・?
と、いうところで、これだけいくつかのフックを駆使しつつ、やっと wp_nav_menu() を使いこなすことができるのだけれども、その上、header と footer と両方に navi menu を生成して、ということになると、やはりどれだけ遅くなってしまうのか!と、いうことが気になってしまう。
ローカル環境でやってみても、そんなに遅くなっているという感じはしないのではあるけれど・・・。それでも、やはり直に html ( php ) を書いてあるものよりは負荷が大きいだろうなぁと思う。そして、html の知識のない人たちには、この機能は必須なのだろうし。
まぁ、ナビメニューなんてものは一度作ってしまえば、そんなに頻繁に変更するものでもないのだし、ならばキャッシュ化してしまえばいいじゃないか、と、いうことで、2ページ目では、その navi menu のキャシュ化について、となります。
Post : 2022/02/22 23:00
Comments feed
Trackback URL : https://strix.main.jp/wp-trackback.php?p=169847