今回はモジュール作りに欠かせない「コントローラー」、そして特定のURLとコントローラーを結ぶ「ルート」についての公式ドキュメントを翻訳したのでご紹介したいと思います。

ですが、その前に「コントローラーって何?」という方のために、Drupalにおけるコントローラーの定義をご紹介・・・したかったのですが、見当たらなかったので、Drupalが多くの部分を継承しているSymfonyというフレームワークにおけるコントローラーの定義をご紹介します。

コントローラーとはリクエストオブジェクトから情報を読み取り、レスポンスオブジェクトを返すPHPの関数です。レスポンスはHTMLページ、JSON、XML、ファイルのダウンロード、ページのリダイレクト、404エラーなど、なんでもOKです。コントローラーはあなたのアプリケーションがページをレンダリングするために必要とする任意のロジックを実行します。

ルーティングは特定のURLへのアクセスがあった時に指定されたコントローラーが実行されるように設定することを言い、ルートとはその設定された経路を指します。例えば、/blogというURLにアクセスがあった時にBlogController.phpというファイルの中のcontent()というコントローラーメソッドを実行するように設定することがルーティングにあたります。


(翻訳開始)

作成例で学ぶDrupal8のルーティングとコントローラー入門

原文: Introductory Drupal 8 routes and controllers example(翻訳時最終更新日:2018年7月10日)

この章はDrupal8におけるルーティングとコントローラーについての簡単な入門です。もしすでにある機能を調節したり拡張したいだけなら、おそらくルーティングについて知る必要はないでしょう。しかし、もしコンテンツや機能を自分のサイトのURLに紐付けたいなら、ルーティングはモジュール作成の上でとても大事な作業になってきます。この章は特定のURLに機能を持たせたり、もしくはすでにある機能を調整したり拡張したりするのに役立つことでしょう。

routing.ymlファイルにおけるルーティング

モジュールのinfo.ymlファイルに名前をつけるときは、module_name.info.ymlと名付けます。(訳者注:info.ymlとはDrupalにおいてシステムにモジュールやテーマの存在を知らせるために最初に作るファイルで、モジュール名、説明、モジュールかテーマか、推奨されるDrupalのバージョン、などの情報を含みます。)そのmodule_nameは「マシン名」としてDrupalのコアに登録されます。コアに登録されることで、モジュールの詳細を(管理画面の)モジュールリストから確かめることができるようになります。Drupalはinfo.ymlを登録した後、module_name.routing.ymlと名付けられたルーティングファイルを読み込みます。ルーティングファイルには特定のURLにアクセスがあったときにDrupalがどう振る舞うべきかという情報が書かれています。例えば、example.info.ymlというファイルがモジュールを定義をしているとき、example.routing.ymlというファイルを持つことになります。(.ymlファイルではダブルクオート()ではなくシングルクオート(')を使うことに注意してください。ダブルクオートを使うと予期しない結果を生み出す可能性があります。)

example.content:
  path: '/example' 
  defaults: 
    _controller: '\Drupal\example\Controller\ExampleController::content' 
    _title: 'Hello World'
  requirements: 
    _permission: 'access content' 

上記のコードは「Drupal8にexample.contentと呼ばれるルートが存在し、それが/exampleというURLに結び付けられている」ことを示しています。このURLにアクセスがあると、アクセスしたユーザーに'access content'という権限があるかどうかがチェックされ、それが認証されると、(モジュールフォルダ内の別のファイルに存在する)ExampleController::contentメソッドが呼び出され、「Hello World」というタイトルとともにページが表示されます。

Drupalのオートロード機構がmodules/example/src/Controller/ExampleController.phpにあるファイルを読み込んだことに注目してください。これはなぜかというと、Drupalが_controllerにあるモジュールのマシン名exampleを発見すると、モジュールのsrcフォルダを見に行くようになっているためです。もしコントローラーがオートロードされなかった場合は、マシン名を確かめることをお勧めします。

Drupal7でモジュールを作ったことがある方なら、Drupal7がhook_menu()を使ってページコールバックとパスを結びつけた方法ととても似ていることに気づくと思います。(ですが、Drupal8 のルーティングシステムはタブ管理やアクションリンク、コンテクスチュアルリンクとは関係がありません。)

ページコントローラーを作る

Drupal8はSymphonyのHTTPカーネルを使っています。SymphonyのHTTPカーネルはリクエストを受け取り、システムに対して必要なアウトプット(レスポンスオブジェクト)を作るように指示し、クライアントにリスポンスを送る役割を果たしています。そのアウトプットは「コントローラー」と呼ばれる一片のコードによって生成されています。理論的には、コントローラーは純粋なPHP4の関数でもいいし、オブジェクト内のメソッドでもいいし、無名の関数でも大丈夫です。ルーティングシステムの詳細についてはこちらをご覧ください

コンテンツをアウトプットするページを作る二つ目のパートはページコントローラーをきちんとした形式にすることです。PHP4の関数にするのもアリですが、Drupal8におけるベストプラクティスはコントローラークラスを使うことです。そのコントローラーは先述のルーティングファイルで使われたコントローラーと全く同じく、ExampleController.phpという名前のファイルに入れます。

Drupal8はPSR-4に準拠しています。それはつまり、先述したようなルーティングに対しては、コントローラークラスはexample/src/Controllerというディレクトリの中に、ExampleController.phpという名前で置かなければならないということです。そのため、フルパスはexample/src/Controller/ExampleController.phpになります。

namespace Drupal\example\Controller;

use Drupal\Core\Controller\ControllerBase;

/**
 * An example controller.
 */
class ExampleController extends ControllerBase {

  /**
   * Returns a render-able array for a test page.
   */
  public function content() {
    $build = [
      '#markup' => $this->t('Hello World!'),
    ];
    return $build;
  }

}

というわけで、ルーティングファイルとページコントローラーのみで、/exampleというページに「Hello World」というタイトルとともに「Hello World!」と表示するページを作ることが出来ました。

(翻訳終わり)


訳者注

  • content()の関数名は、routing.yml内の設定と一致するなら、何でも大丈夫です。
  • example/src/Controller/ExampleController.phpcontent()の以下の配列は、レンダリング配列と呼ばれるものです。ここをルールに従って設定してリターンすることで、Drupalが勝手に読み取ってHTMLに変換してくれます。
$build = [
      '#markup' => $this->t('Hello World!'),
    ];

レンダリング配列についてはこちらをご覧ください。