【Drupal】テーマ3 
~オリジナルリージョン作成~

前回の続きです。

今回はオリジナルのリージョンを作ってみましょう。

結論から言いますと、オリジナルのリージョンを作るためには、info.ymlファイルに新しくリージョン名を定義し、

page.html.twigファイルに「page.定義したリージョン名」を記載するだけでいいのです!

仕事でリージョンを調査するときとかにネットを漁ると、大体はこのような説明です。

しかし、「なぜそのような操作をすればリージョンが実装されるのか」については知っておく必要があると思うのです。

そのため、まずはinfo.ymlがどのように読み込まれるかというところから考えていきましょう。

簡単にですがDrupalのcore部分を確認した結果、以下の箇所でpage.html.twigにリージョン名を渡しているようでした。
core/includes/theme.inc

~略~
/**
 * Prepares variables for the page template.
 *
 * Default template: page.html.twig.
 *
 * See the page.html.twig template for the list of variables.
 */
function template_preprocess_page(&$variables) {
  $language_interface = \Drupal::languageManager()->getCurrentLanguage();

  foreach (\Drupal::theme()->getActiveTheme()->getRegions() as $region) {
    if (!isset($variables['page'][$region])) {
      $variables['page'][$region] = [];
    }
  }

~略~

「\Drupal::theme()->getActiveTheme()->getRegions()」が何をしているかというと、
サービスという機能を使って「core/lib/Drupal/Core/Theme/ThemeManager.php」のThemeManagerクラスから、
リージョン名を取得しています。「getActiveTheme()」というところからも、現在有効であるテーマに対して、リージョン名をとってきてそうですよね。

ちなみにgetActiveThemeは以下のような定義です。

~略~
  public function getActiveTheme(RouteMatchInterface $route_match = NULL) {
    if (!isset($this->activeTheme)) {
      $this->initTheme($route_match);
    }
    return $this->activeTheme;
  }
~略~

現在有効であるテーマのオブジェクト「activeTheme」を取り出すわけですね。

オブジェクト「activeTheme」には、ActiveTheme.phpで定義されている、
info.ymlファイルの情報が詰まっている変数が格納されているので、そこからinfo.ymlの情報を取得できるというわけです。

どうやってinfo.ymlを読み込んでいるかというと、最終的には「core/lib/Drupal/Core/Extension/InfoParserDynamic.php」の

関数parseを呼び出し、PHPの関数file_get_contentsを使って読み込んでいるようです。

~略~
  public function parse($filename) {
    if (!file_exists($filename)) {
      $parsed_info = [];
    }
    else {
      try {
        $parsed_info = Yaml::decode(file_get_contents($filename));
      }
~略~

とりあえずこれで、info.ymlファイルが読み込まれる仕組みが分かったかと思います。

Drupalって中身が見えづらいので、

「なんか言われるままinfo.ymlファイルをいじってみたらうまくいきましたー」

で終わらせてしまいがちです。。私はそうでした。

分からないことを分からないまま進めず、一つ一つ理解していくことが大事だと思っています。

サービスとは

Drupalのサービスとは、つまりは「DIコンテナ」のことです。
DIコンテナって何?となるかと思います。
一言でいうとDIコンテナとは、オブジェクト同士の繋がりを弱くしたオブジェクト作成の方法を、自動で実施する機能です。
オブジェクトと呼ばれるクラスの実態を作る際、クラスの中でオブジェクトを作らず、引数にオブジェクトを渡すことがあります。
これがDI(Dependency Injection:依存性注入)です。
DIを使う理由としては、クラスに変更があった際に改修箇所が減るし、プログラムのテストがやりやすくなるからです。
ただ、オブジェクトを作成するときに毎回毎回引数にオブジェクトを書く処理を書くのは面倒なわけです。
そこで、オブジェクトの作成を実施してもらう機能として「DIコンテナ」が存在するわけですね。
以下のようなイメージです。
「classAを下さい」は、Drupalでは「get(‘theme.manager’);」のように書きます。
Drupalがコアとして提供するサービスは全て「core/core.services.yml」に書かれているので、眺めてみてください。

上記にも書きましたが、「template_preprocess_page」でpage.html.twigにリージョン名を渡しています。
「template_preprocess_page」は、ThemeManager.phpの以下の箇所で呼ばれます。これはthemeに関するhookを実行する箇所っぽいです。

core/lib/Drupal/Core/Theme/ThemeManager.php

~略~
    if (isset($info['preprocess functions'])) {
      foreach ($info['preprocess functions'] as $preprocessor_function) {
        if (function_exists($preprocessor_function)) {
          $preprocessor_function($variables, $hook, $info);
        }
      }
~略~

「template_preprocess.~」は、info.ymlファイルに定義されたリージョンを読み込み、$variables[‘page’][$region]として定義します。

そして、「~」に当たる部分の文字列.html.twigで、$variablesに定義された変数が使用できるのです。

いよいよオリジナルのリージョンを作りましょう!

といってもとても単純で、以下のように、info.ymlファイルにリージョン名を新しく作っちゃいましょう。
themes/Custom/okitheme/okitheme.info.ymlの記述内容

~略~
regions:
~略~
  oki_region: 'テスト的に作ったリージョンです。'
~略~

この状態で「サイト構築」-「ブロックレイアウト」を見てください。

おおーありますね。しかし、「サイト構築」-「ブロックレイアウト」-「ブロックリージョンを仮表示する」を見てください。

ありませんね~。これは、page.html.twigに新しいリージョン名が記載されていないからです。
以下を記載してみましょう。

/themes/Contrib/bartik/templates

~略~
<div id="page-wrapper">
  <div id="page">
    <header id="header" class="header" role="banner">
      <div class="section layout-container clearfix">
        {{ page.secondary_menu }}
        {{ page.header }}
        {{ page.primary_menu }}
      </div>
    </header>
        {{ page.oki_region }}
~略~

表示されましたね!これで、自分でhtml上にリージョンを作ることができたわけです。

以上で、テーマにリージョンを追加することができました。

テーマを極めれば、Drupalサイトのデザインが自由自在です。

私はこの本(Drupal 9 Module Development)でDrupalの 勉強をしています。
Drupal9に関する日本語の本にはない、Drupalの具体的な実装方法が記載されています。