9.7. Drupal のプラグイン。プログラムでブロックを追加する方法。
このチュートリアルでは、Drupal 8 でカスタムモジュールを通じてプログラムでブロックを出力する方法を見ていきます。
コード例は github で見られます:
https://github.com/levmyshkin/drupalbook8
まず、PHP クラスを含むファイルを追加することから始めましょう。これが、カスタムモジュールを通じて Drupal でブロックが作成される方法です。ファイルを作成するプロセスは、ここで行ったページ用のクラスと同じです:
9.3. カスタム Drupal モジュールを作成する。プログラムでページを出力する。
ただし、プラグインを含むファイルを作成する必要があります:
modules/custom/drupalbook/src/Plugin/Block/FirstBlock.php

このブロックコードをコピーして、次に各コード片を解析しましょう
modules/custom/drupalbook/src/Plugin/Block/FirstBlock.php:
<?php
namespace Drupal\drupalbook\Plugin\Block;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Block\BlockBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Session\AccountInterface;
/**
* Provides a block with a simple text.
*
* @block(
* id = "drupalbook_first_block_block",
* admin_label = @block("My first block"),
* )
*/
class FirstBlock extends BlockBase {
/**
* {@block}
*/
public function build() {
$config = $this->getConfiguration();
if (!empty($config['drupalbook_first_block_settings'])) {
$text = $this->t('Hello @Name in block!', ['@Name' => $config['drupalbook_first_block_settings']]);
}
else {
$text = $this->t('Hello World in block!');
}
return [
'#markup' => $text,
];
}
/**
* {@block}
*/
protected function blockAccess(AccountInterface $account) {
return AccessResult::allowedIfHasPermission($account, 'access content');
}
/**
* {@block}
*/
public function blockForm($form, FormStateInterface $form_state) {
$config = $this->getConfiguration();
$form['drupalbook_first_block_settings'] = [
'#type' => 'textfield',
'#title' => $this->t('Name'),
'#description' => $this->t('Who do you want to say hello to?'),
'#default_value' => !empty($config['drupalbook_first_block_settings']) ? $config['drupalbook_first_block_settings'] : '',
];
return $form;
}
/**
* {@block}
*/
public function blockSubmit($form, FormStateInterface $form_state) {
$this->configuration['drupalbook_first_block_settings'] = $form_state->getValue('drupalbook_first_block_settings');
}
}

私たちのブロックを Left Sidebar リージョン、または都合の良い別のカラムに表示します。

ブロックの名前を入力し始めると、Drupal が自動的にあなたのブロックを選ぶよう促します。ブロックがそこにない場合は、目的のコードが正しいファイルにあり、ファイルが正しいフォルダーにあるか確認し、その後キャッシュをクリアするのを忘れないでください。

ブロックが表示されたので、ブロックを追加するコードがどう動作するか見てみましょう:

ファイルの先頭には namespace があります。これは、Drupal が自動的に接続できるように、ブロックプラグインファイルがどこにあるべきかを決定するためのものです。また、use を使って他のファイルからクラスを含めます。
\drupalbook\Plugin\Block;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Block\BlockBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Session\AccountInterface;
Further in the comments is the annotation. We don’t need to define the block somewhere in the YML files, it will be automatically loaded by the Drupal using annotation.
/**
* Provides a block with a simple text.
*
* @block(
* id = "drupalbook_first_block_block",
* admin_label = @block("My first block"),
* )
*/
ここでは @block に、それがブロックプラグインであることを示します。id、admin_label は Drupal によって自動的に拾われるので、id は一意でなければなりません。@block は、その後 Drupal 管理パネルを通じてブロックラベルを翻訳するのに役立ちます。
extends BlockBase {
BlockBase クラスから継承します。PhpStorm で ctrl を押しながら BlockBase をクリックすると、私たちのブロックでどのメソッドを再定義できるか見られます。それらすべてを使うわけではありません。必要に応じて他のメソッドをオーバーライドできます。
クラスのメソッドをさらに見てみましょう:
/**
* {@block}
*/
protected function blockAccess(AccountInterface $account) {
return AccessResult::allowedIfHasPermission($account, 'access content');
}
この記事でページへのアクセスをすでに検討しました。ブロックでは同じアクセス権を使えます:
https://drupalbook.org/ru/drupal/126-rout-s-parametrom
ここでは同じ AccessResult クラスを使います。
/**
* {@block}
*/
public function blockForm($form, FormStateInterface $form_state) {
$config = $this->getConfiguration();
$form['drupalbook_first_block_settings'] = [
'#type' => 'textfield',
'#title' => $this->t('Name'),
'#description' => $this->t('Who do you want to say hello to?'),
'#default_value' => !empty($config['drupalbook_first_block_settings']) ? $config['drupalbook_first_block_settings'] : '',
];
return $form;
}
プログラムで作成する各ブロックに、個別のブロック構成フォームを使えます。ブロック設定に移動すると:

ここで、blockForm() メソッドで追加した Name フィールドが見られます:

フォームのフィールドを作成するために Drupal Form API を使います:
https://www.drupal.org/docs/8/api/form-api
https://api.drupal.org/api/drupal/elements/8.5.x
Form API については今後詳しく分析し、マルチステップのポップアップフォームを作ります。とりあえず、Form API を使ってどんな他のタイプのフィールドを使えるか見られます。各フィールドは配列を使って追加されます。ブロックフォームにもっとフィールドを追加してみてください。
/**
* {@block}
*/
public function blockSubmit($form, FormStateInterface $form_state) {
$this->configuration['drupalbook_first_block_settings'] = $form_state->getValue('drupalbook_first_block_settings');
}
ここでは、フォームのフィールドの値を Drupal の構成に保存します。構成についても次のレッスンで詳しく検討しますが、とりあえず、Drupal にはすべての構成の共通ストレージがあり、すべてのモジュールがこの構成のストレージを使うことを理解しておく必要があります。これらの構成は、あなたのある サイトから別のサイトに移せます。例えば、サイトのローカルコピーでブロック設定を変更した場合、これらの構成をアップロードして live サイトに反映でき、live サイトでブロック設定を適用できます。
/**
* {@block}
*/
public function build() {
$config = $this->getConfiguration();
if (!empty($config['drupalbook_first_block_settings'])) {
$text = $this->t('Hello @Name in block!', ['@Name' => $config['drupalbook_first_block_settings']]);
}
else {
$text = $this->t('Hello World in block!');
}
return [
'#markup' => $text,
];
}
そして、ブロックのコンテンツを表示するメインの build() メソッドです。このメソッドでは、ブロックの構成を確認し、Name があれば名前付きのテキストを表示します。$this->t() メソッドに注意してください。これにより、Drupal 管理パネルを通じてテキストを他の言語に翻訳できます。また、プレースホルダー @Name を使います。これは、構成フォームで入力するフィールドの値ではなく、目的のテキストだけを翻訳するために必要です。これにより、複数行の翻訳を避けられます。例えば、プレースホルダーを使わないと、$this->t() を通るテキストのすべてのバリエーションが管理パネルで翻訳可能になります:
Hello Josh ...
Hello Mike ...
Hello Ivan ...
など。
Drupal 8 でカスタムブロックをどう表示・構成するかが明確になったと思います。次に、ブロック、ページ、フォームを使ったより複雑な例を検討します。
コード例は github で見られます:
https://github.com/levmyshkin/drupalbook8