Drupalではメニューのアイテムのことをメニューリンクといいます。メニューリンクの作り方には以下の3種類があります。

  • 管理画面から作る
  • links.menu.ymlを書く(YAML)
  • MenuLinkContentエンティティを生成するプログラムを書く(PHP)

今回はこれらの方法や特性について詳しく解説したいと思います。

管理画面から作る

管理画面からメニューを作ると、バックエンドではMenuLinkContentというエンティティが作成され、DBのmenu_linkで始まるテーブルに保存されます。MenuLinkContentエンティティには以下のような特性があります。

  • 管理画面から編集・削除可能
  • コンテンツの翻訳を通じて翻訳可能

実際のプロジェクトではサイトのナビゲーションなどは管理画面から作ることが多いのではないかと思います。管理画面からのメニューリンクの作り方は以下のようになります。

  • メニュー一覧(/admin/structure/menu)に移動
  • 任意のメニューのメニューの編集をクリック
  • メニュー編集画面(/admin/structure/menu/manage/[MENU_NAME])にてリンクの追加をクリック
  • メニューリンクのタイトルとリンク先を入力して保存

メニューリンクを作成すると以下のように表示されます。

links.menu.ymlを書く

続いて、links.menu.ymlで作る方法を紹介します。この方法はコアやコントリビュートモジュールでメニューリンクを作るときの標準的な方法として使われています。

この方法で作られるメニューリンクには以下のような特性があります。

  • エンティティは作られず、代わりにYAMLの構成をパースした結果がDBのmenu_treeに保存される
  • 管理画面から削除できない。またタイトルとパスは編集できない
  • カスタムモジュールをアンインストールするとサイト上から消える
  • インターフェースの翻訳を通じて翻訳可能

管理画面から編集できないという特性から、カスタムモジュールを使う際に無くてはならないメニューリンクを作成するのに向いている方法です。

作り方は以下のようになります。まずカスタムモジュールを作成し、モジュールディレクトリ直下に[MY MODULE}.links.menu.ymlというファイルを作成します。

mymodule
└mymodule.info.yml
└mymodule.links.menu.yml

今回はさきほど管理画面で編集したmy_menuというメニューにEFというメニューリンクを追加してみます。FEの子アイテムとします。

links.menu.ymlの中身を以下のように編集します。

mymodule.e: 
  title: 'E'
  description: 'Menu Item E'
  menu_name: my-menu 
  url: internal:/test

mymodule.f:
   title: 'F'
   description: 'Menu Item F'
   menu_name: my-menu
   parent: mymodule.e
   url: internal:/test

モジュールを有効化するとこのようにメニューが生成されます。

それぞれ編集画面にアクセスはできますが、タイトルとパスは編集できません。

YAMLを書く際の主な注意点は以下になります。

  • マシン名(mymodule.e)のmymoduleの部分はモジュールのマシン名
  • titleは必須
  • urlroute_nameにするとルートでも指定可。urlroute_nameのどちらかが必須
  • menu_nameが無い場合はtoolsが使われる

そのほかのキーの詳しい情報はこちらをご覧ください。
function hook_menu_links_discovered_alter

管理画面のメニューもlinks.menu.ymlで簡単に子アイテムを増やすことができます。例えば環境設定(/admin/config)に項目を追加する場合は以下のように書きます。

mymodule.settings:
   title: 'My Module'
   parent: system.admin_config # 環境設定の子アイテムにする
   url: internal:/test

mymodule.:
   title: 'My Module Settings'
   description: 'Configure My Module'
   parent: mymodule.settings
   url: internal:/test

結果はこのようになります。

ちなみに環境設定のマシン名はcore/modules/system/system.links.menu.ymlで確認することができます。

MenuLinkContentエンティティを生成するプログラムを書く

最後に、カスタムコードでMenuLinkContentエンティティを生成する方法を紹介します。この方法で作られるメニューリンクの特性は以下のようになります。

  • 管理画面から編集・削除可能
  • コンテンツの翻訳を通して翻訳可能
  • 一度生成されたメニューリンクはカスタムモジュールをアンインストールしてもDBに残る
  • PHPなのでパラメーターを動的に変えられる

MenuLinkContentエンティティをカスタムモジュールで実装する場合は以下のようなコードになります。今回は先程追加したFの子アイテムとしてGというメニューリンクを追加してみます。

<?php
use Drupal\menu_link_content\Entity\MenuLinkContent;

/**
 * Implements hook_install().
 */
function my_module_install() {

    $menu_link = MenuLinkContent::create([
    'title' => t('G'),
    'link' => ['uri' => 'internal:/test'],
    'menu_name' => 'my_menu',
    'parent' => 'mymodule.f',
    'expanded' => TRUE,
    'weight' => 200,
    ]);

    $menu_link->save();
}

結果のスクショです。

今回はhook_installを使いましたが、hookの種類は何でも大丈夫です。create()内のパラメーターを変数にすればメニューリンクを動的に生成することができます。

終わりに

というわけで、メニューリンクの作り方の紹介でした。それぞれできること・できないことがあるので、場面に合わせて使い分けていきましょう!


共に働く新しい仲間を
募集しています

スタジオ・ウミは「Drupal」に特化したサービスを提供する Drupal のエキスパートチーム。
フルリモート&フレックス制だから、働く場所を選ばず時間の使い方も自由です。
そんなワークライフバランスの整った環境で、当ブログに書かれているような
様々な技術を共に学びながら、Drupalサイト開発に携わってみたい方を募集しています。
まずはお話だけでも大歓迎!ぜひお気軽にご連絡ください。