Drupalモジュールの基本構造
パートII:Drupal 8の基本モジュール作成の実践ガイド
.infoからテストまで、基礎のみ
基本構造
loremipsum.info.yml
name: Lorem ipsum
type: module
description: 'Lorem ipsum generator for Drupal'
package: Development
core: 8.x
configure: loremipsum.form
インフォファイルは現在YML形式でフォーマットされており、type宣言でモジュールとテーマの区別がわかります。configure宣言はルートを指しています(詳細は後ほど説明します)が、それ以外には何もありません。実際、これがモジュールに必要な唯一のファイルです。これを(root/modulesフォルダに)保存した後、サイトを壊すことなく/admin/modulesでモジュールを有効化できます。ただし、これから説明するように、それだけでは十分ではありません。
loremipsum.module
<?php
use Drupal\Core\Routing\RouteMatchInterface;
/**
* Implements hook_help().
*/
function loremipsum_help($route_name, RouteMatchInterface $route_match) {
switch ($route_name) {
case 'help.page.loremipsum':
return t('
<h2>Lorem ipsum generator for Drupal.</h2>
<h3>Instructions</h3>
<p>Lorem ipsum dolor sit amet... <strong>Just kidding!</strong></p>
<p>Unpack in the <em>modules</em> folder (currently in the root of your Drupal 8 installation) and enable in <strong>/admin/modules</strong>.</p>
<p>Then, visit <strong>/admin/config/development/loremipsum</strong> and enter your own set of phrases to build random-generated text (or go with the default Lorem ipsum).</p>
<p>Last, visit <strong>www.example.com/loremipsum/generate/P/S</strong> where:</p>
<ul>
<li><em>P</em> is the number of <em>paragraphs</em></li>
<li><em>S</em> is the maximum number of <em>sentences</em></li>
</ul>
<p>There is also a generator block in which you can choose how many paragraphs and
phrases and it\'ll do the rest.</p>
<p>If you need, there\'s also a specific <em>generate lorem ipsum</em> permission.</p>
<h3>Attention</h3>
<p>Most bugs have been ironed out, holes covered, features added. But this module is a work in progress. Please report bugs and suggestions, ok?</p>
');
}
}
少なくともhook_help()呼び出しをここに置くことは良い習慣です。また、RouteMatchInterfaceクラスを指すuseステートメントにも注意してください。これは主にhook_menu()が存在しなくなったためです。
...そして先に進むにつれて、.moduleファイルがテーマ情報の保存にも使用されることに気付くでしょう。だから保管しておいてください。
loremipsum.install
<?php
/**
* @file
* Installation functions for Lorem ipsum module.
*/
use Drupal\user\RoleInterface;
/**
* Implements hook_install().
*/
function loremipsum_install() {
user_role_change_permissions(RoleInterface::ANONYMOUS_ID, array(
'generate lorem ipsum' => TRUE,
));
}
ここでは別のクラス:RoleInterfaceを使用します。基本的に、このファイルはDrupalに「このモジュールが有効になったら、generate lorem ipsum権限を見つけて有効にしてください」と伝えます。
しかし、その権限はどこで定義されていますか?
loremipsum.permissions.yml
generate lorem ipsum:
title: 'Generate Lorem ipsum'
ご覧のとおり、hook_permission()呼び出しよりはるかに簡単です。完全な構文はPermissionHandlerのドキュメントにあります。
loremipsum.routing.yml
loremipsum.generate:
path: '/loremipsum/generate/{paragraphs}/{phrases}'
defaults:
_controller: '\Drupal\loremipsum\Controller\LoremIpsumController::generate'
requirements:
_permission: 'generate lorem ipsum'
loremipsum.form:
path: '/admin/config/development/loremipsum'
defaults:
_form: '\Drupal\loremipsum\Form\LoremIpsumForm'
_title: 'Lorem ipsum settings'
requirements:
_permission: 'administer site configuration'
ルーティングファイルはhook_menu()呼び出しを置き換えます。各エントリ(インデントなし)はルートを指し、その後に特定の設定を詳述するインデント付きの行が続きます。
loremipsum.generateルートは{}内の2つの引数を受け取るページを指しており、コントローラーに対応します(詳細は後述)。対照的に、loremipsum.formはタイトル付きの(設定)フォームを指しています。
両方のルートには権限が必要ですが、無制限アクセスのために_access: 'TRUE'に置き換えることができます。
loremipsum.services.yml
カスタムサービスを宣言できます。
loremipsum.links.menu.yml
loremipsum.form:
title: 'Lorem Ipsum settings'
description: 'Configure settings for the Lorem Ipsum module.'
route_name: loremipsum.form
parent: 'system.admin_config_development'
ルーティングファイルが/admin/config/development/loremipsumにページを作成する一方で、管理メニューにページを追加するにはこれらの定義が必要です。
loremipsum.links.task.yml
特定のルートの追加のローカルタスク(タブ)を作成するための定義。
loremipsum.links.action.yml
特定のルートの追加のローカルアクション(ボタン)を作成するための定義。
loremipsum.links.contextual.yml
特定のUI要素の追加のコンテキストアクションを作成するための定義。
loremipsum.libraries.yml
CSSおよびJavaScriptライブラリの依存関係を記録するために使用されます。詳細は関連セクションを参照してください。
README.md
* modules *フォルダに解凍し(現在はDrupal 8インストールのルートにあります)、`/admin/modules`で有効化します。
次に、`/admin/config/development/loremipsum`に移動し、独自のフレーズセットを入力してランダムに生成されたテキストを構築します(またはデフォルトのLorem ipsumを使用します)。
最後に、`www.example.com/loremipsum/generate/P/S`にアクセスします。ここで:
- * P * - *段落*の数
- * S * - *文*の最大数
また、ジェネレーターブロックもあり、そこでは段落とフレーズの数を選択でき、残りは自動的に行われます。
必要に応じて、専用の* generate lorem ipsum *権限もあります。
注意
---------
ほとんどのバグは修正され、穴は塞がれ、機能が追加されています。ただし、このモジュールは進行中の作業です。バグや提案があれば報告してくださいね?
そうです、READMEファイルは現在マークダウン形式で書かれています。私に言わせればかなりクールです。
それでは、特定の詳細を詳しく調べるためにフォルダーをさらに掘り下げてみましょう。
LICENSE.TXT
LICENSE.txt(または類似のファイル)を含めないでください。パッケージングスクリプトがこれを追加します。
/config/install/loremipsum.settings.yml
loremipsum:
page_title: 'Lorem ipsum'
source_text: "Lorem ipsum dolor sit amet, consectetur adipisci elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \nUt enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. \nDuis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. \nExcepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. "
このファイルには、次のファイルを通じて適切なフィールドに割り当てられるデフォルト設定が保存されます:
loremipsum:
page_title: 'Lorem ipsum'
source_text: "Lorem ipsum dolor sit amet, consectetur adipisci elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \nUt enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. \nDuis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. \nExcepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. "
このファイルには、次のファイルを通じて適切なフィールドに割り当てられるデフォルト設定が保存されます:
/config/schema/loremipsum.schema.yml
loremipsum.settings:
type: config_object
label: 'Lorem Ipsum settings'
mapping:
loremipsum:
type: mapping
mapping:
page_title:
type: text
label: 'Lorem ipsum generator page title:'
source_text:
type: text
label: 'Source text for lorem ipsum generation:'
block.settings.loremipsum_block:
type: block_settings
label: 'Lorem ipsum block'
mapping:
loremipsum_block_settings:
type: text
label: 'Lorem ipsum block settings'
スキーマファイルは、モジュール用にカスタムテーブルを定義しない場合でも使用されます。ここでは、設定フォームのフィールドに割り当てられるデフォルト値を確認できます。
このコードの開発中に、フィールドを「そのまま」で埋めることが最も難しいタスクの1つであることに気付きました。幸いなことに、これを行うためのモジュールがあります:Drupal 8用の設定インスペクター。これにより、デフォルト設定のデバッグができます。
さらに、YMLスキーマファイルは多くの点で非常に役立ちます。
/src/Controller/LoremIpsumController.php
<?php
namespace Drupal\loremipsum\Controller;
// Change following https://www.drupal.org/node/2457593
// See https://www.drupal.org/node/2549395 for deprecate methods information
// use Drupal\Component\Utility\SafeMarkup;
use Drupal\Component\Utility\Html;
// use Html instead SAfeMarkup
/**
* Controller routines for Lorem ipsum pages.
*/
class LoremIpsumController {
/**
* Constructs Lorem ipsum text with arguments.
* This callback is mapped to the path
* 'loremipsum/generate/{paragraphs}/{phrases}'.
*
* @param string $paragraphs
* The amount of paragraphs that need to be generated.
* @param string $phrases
* The maximum amount of phrases that can be generated inside a paragraph.
*/
public function generate($paragraphs, $phrases) {
このモジュールの中核である、プレースホルダーテキストを生成する単一のメソッドを持つクラスに到達しました。ご覧のとおり、LoremIpsumControllerクラス内で生成されたメソッドは、YMLルーティングファイルのエントリを参照しています:

白い枠にはファイルのコードが示されています:loremipsum.routing.ymlと、作業中のファイルの背景です。
それでは続けましょう。次のコードスニペットはモジュールの設定を取得し、後で使用するために保存します:
// Default settings.
$config = \Drupal::config('loremipsum.settings');
// Page title and source text.
$page_title = $config->get('loremipsum.page_title');
$source_text = $config->get('loremipsum.source_text');
上記のパラメーター(loremipsum.page_titleとloremipsum.source_text)は、YAML設定ファイルから取得されます:

次に、$source_textからフレーズを配列に分割します:
$repertory = explode(PHP_EOL, $source_text);
そして、この配列を使用してテキストの段落を構築します:
$element['#source_text'] = array();
// Generate X paragraphs with up to Y phrases each.
for ($i = 1; $i <= $paragraphs; $i++) {
$this_paragraph = '';
// When we say "up to Y phrases each", we can't mean "from 1 to Y".
// So we go from halfway up.
$random_phrases = mt_rand(round($phrases / 2), $phrases);
// Also don't repeat the last phrase.
$last_number = 0;
$next_number = 0;
for ($j = 1; $j <= $random_phrases; $j++) {
do {
$next_number = floor(mt_rand(0, count($repertory) - 1));
} while ($next_number === $last_number && count($repertory) > 1);
$this_paragraph .= $repertory[$next_number] . ' ';
$last_number = $next_number;
}
//$element['#source_text'][] = SafeMarkup::checkPlain($this_paragraph);
$element['#source_text'][] = Html::escape($this_paragraph);
}
['#source_text']はテンプレートに渡されるレンダー配列であり、この配列の各要素がセキュリティのためにHtml::escape()を通過することに注意してください。
最後に、レンダー配列にタイトルを付け、テーマ関数を割り当てて返します:
//$element['#title'] = SafeMarkup::checkPlain($page_title);
$element['#title'] = Html::escape($page_title);
// Theme function.
$element['#theme'] = 'loremipsum';
return $element;
}
}
しかし、この変数をテンプレートに渡す前に、それらを処理する必要があります。
次のステップ:
テーマ化モジュール。
その次に:
このモジュール用のブロックの定義。
このモジュール用のテストの作成。