9.3. カスタム Drupal モジュールを作成する。プログラムでページを表示する。
私たちのモジュールの作成を、少し整理することから始めましょう。引き続きカスタムモジュールと contrib モジュールを分けましょう。Drupal ではモジュールは /modules フォルダーにあります。今では /sites/all/modules に深く入れる必要はありません。readme にはそれで動作すると書かれていますが、やはり /modules フォルダーを使ってください。/modules フォルダーの中に、custom と contrib の 2 つのフォルダーを作成します。contrib フォルダーには drupal.org からの追加モジュールを保存し、私たちのカスタムモジュールは custom フォルダーに保存します。
英語字幕:
コード例は github で見られます:
https://github.com/levmyshkin/drupalbook8
モジュールを contrib、custom フォルダーに分けるようなささいなことは、とても不要に思えますが、信じてください。サイトに 200 の contrib モジュールと 30 のカスタムモジュールがあると、サイト上のすべてのカスタムモジュールとすべてのカスタムコードを見つけるのがいかに難しいか分かるでしょう。また、contrib モジュールのコードを変更する場合(これは絶対に必要な場合にのみ行うべきです)、それを custom フォルダーに移しておくのも良いでしょう。そうすれば、更新中に誤って変更を上書きしたり(あるいは別のプログラマーがあなたの変更を上書きしたり、あるいはあなた自身が何も疑わずに別のプログラマーの変更を上書きしたり)しません。

それでは、カスタムモジュールを作成しましょう。フォルダー /modules/custom/drupalbook を作成します。このフォルダーには drupalbook.info.yml ファイルを作成する必要があります:
name: DrupalBook
description: Custom module for learning Drupal 8
type: module
core: 8.x
core_version_requirement: ^8 || ^9
package: DrupalBook
*.info.yml ファイルは、モジュールの記述を担当します。その中に示された情報は Extend ページに表示されます。ファイル名自体は、モジュール名 + .info.yml で構成されます。
Drupal の YML ファイルは、構成と設定の標準的な形式です。YML ファイルのフィールドと値はコロンで区切られ、新しい行は 2 スペースのインデントで始まります。YML ファイルにとってフォーマットは非常に重要で、フォーマットにミスがあったり、余分なスペースがあったり、コロンが欠けていたりすると、Drupal がエラーを出すか、YML ファイルが正しく読み取れなくなることがあります。
Extend ページに移動し、モジュールを有効にします:

モジュールを組み込んだので、機能を追加でき、それがサイトで動作します。まず、ページにプレーンテキストを表示します。そのために、もう 1 つ YML ファイル drupalbook.routing.yml を作成する必要があります:
drupalbook.first_page:
path: '/first-page'
defaults:
_controller: '\Drupal\drupalbook\Controller\FirstPageController::content'
_title: 'Hello World!'
requirements:
_permission: 'access content'
この YML ファイルに何があるか詳しく見てみましょう。
drupalbook.first_page: - ここには私たちのルートの名前があります。これは、drupal がすべてのルート、パスのリストを収集するパスです。この名前は一意でなければなりません。module_name.route_name を使うのが最善です。というのも、1 つのモジュールに複数のルートを持てるからです:drupalbook.first_page、drupalbook.second_page など。
path: '/first-page' - あなたのルートへのパスです。2 スペースのインデントに注意してください。これは必須なので、tab ボタンでタブを挿入するテキストエディターを使っている場合は、この設定を変更してタブの代わりに 2 スペースにするほうが良いです。
defaults: - デフォルトのルート設定とルートの作成方法を定義します。実は、ルートを作成する方法はいくつかあり、その 1 つが Controller クラスを通じてですが、ルートを動的に作成するための他のクラスを通じても可能です。おそらく後でルーティングを扱うすべての可能性を分析しますが、とりあえず Controller クラスを通じたシンプルな例を検討します。Drupal のルーティングは Symfony から移行し、Symfony のライブラリを使います。Symfony は MVC フレームワークで、とても整っており、他のプロジェクトでも使われています。例えば、これも非常に人気のある MVC フレームワークである Laravel でも。MVC は Model、View、Controller の使用を含みます(ここでの View は Views モジュールではなく、情報を表示するための単なるテンプレートで、Model は情報をデータベースに追加できるエンティティクラスで、Drupal の Entity API がするのとよく似ています)。MVC のコントローラーは、まさにこのレッスンで行っているルーティングのために必要です。
_controller: '\Drupal\drupalbook\Controller\FirstPageController::content' - このパラメーターで、どの PHP クラスがページを表示するかを決めます。クラス名の後の :: で、どの特定のクラスメソッドがページを表示するかを示します。これほど多くのスラッシュは、Drupal があなたの PHP クラスがどのフォルダーにあるかを理解するために必要です。
_title: 'Hello World!' - 私たちのページのタイトル
_permission: 'access content' - このページを閲覧する権限。このページを開くには、ユーザーがこの権限を持つロールを持っている必要があります。
ルーティング用の YML ファイルを追加した後、ページを表示するために PHP クラスを追加する必要があります。そのために、まずモジュールからのクラスファイルの自動接続を理解する必要があります。実は、Drupal には多くのクラスがあり、それらすべてが特定のページを読み込むのに必要なわけではないので、必要なクラスだけを読み込んで作業します。Drupal は PSR-4 クラス用の PHP オートローダーを使います:
https://www.php-fig.org/psr/psr-4/
PHP クラスを示したルートの行を見てみましょう:
\Drupal\drupalbook\Controller\FirstPageController
\Drupal - クラスが Drupal ライブラリを使って接続されることを意味します。Drupal は今では、かなり大きいですが、別のライブラリでもあり、packagist を通じて接続できます:
https://packagist.org/packages/drupal/drupal
次に、どのモジュールを使いたいかを示します:
\drupalbook
その後、モジュールのフォルダー内のクラス名をすぐに示すか、さらなるネストを示します。ただし、その場合すべてのフォルダーはすでに src フォルダーの中にあります。つまり、Controller フォルダーを指定した場合、それはここにあります:
/modules/custom/drupalbook/src/Controller
大文字小文字に注意してください。PHP は大文字小文字を区別するので、controller と Controller は異なるフォルダーです。
そして最後に、ファイル名を指定しました。それに .php を追加する必要があります:
/modules/custom/drupalbook/src/Controller/FirstPageController.php
このファイルを作成しましょう:
/**
* @return
* Contains \Drupal\drupalbook\Controller\FirstPageController.
*/
namespace Drupal\drupalbook\Controller;
/**
* Provides route responses for the DrupalBook module.
*/
class FirstPageController {
/**
* Returns a simple page.
*
* @return array
* A simple renderable array.
*/
public function content() {
$element = array(
'#markup' => 'Hello World!',
);
return $element;
}
}
これがファイルの構造になるはずです:

次に、新しいルートが接続されるようにキャッシュをクリアする必要があります。そして、ページが機能するはずです http://drupalbook/first-page:

それでは、このページを表示する PHP クラスを見てみましょう。
/**
* @return
* Contains \Drupal\drupalbook\Controller\FirstPageController.
*/
ここでは、ルーティング YML ファイルと同じパスを示します。これは、Drupal がこのクラスをどこから接続すべきかを示します。
namespace Drupal\drupalbook\Controller;
namespace はあなたのクラスファイルへのパスを示します。他のサイトからコードをコピーするときは注意してください。namespace をコピーするとき、モジュールの名前を自分のものに変える必要があります。私は drupalbook ですが、あなたは別の何かかもしれません。
class FirstPageController {
/**
* Returns a simple page.
*
* @return array
* A simple renderable array.
*/
public function content() {
$element = array(
'#markup' => 'Hello World!',
);
return $element;
}
}
そして、ページを表示する私たちのクラスです。drupalbook.routing.yml で指定した content() メソッドがあります。このメソッドでは、出力に HTML を入れた #markup 要素を持つ配列を返します。文字列ではなく配列を返すのは、通常のルートを通じて HTML だけでなく、API 用の JSON エンドポイント、XML、CSV ファイルも表示できるからです。
モジュールのコードは github で見られます:
https://github.com/levmyshkin/drupalbook8
次のレッスンではこれで終わりです。引き続き私たちのモジュールの機能を拡張します。