logo

额外区块类型 (EBT) - 全新的布局构建器体验❗

额外区块类型 (EBT) - 样式化、可定制的区块类型:幻灯片、标签页、卡片、手风琴等更多类型。内置背景、DOM Box、JavaScript 插件的设置。立即体验布局构建的未来。

演示 EBT 模块 下载 EBT 模块

❗额外段落类型 (EPT) - 全新的 Paragraphs 体验

额外段落类型 (EPT) - 类似的基于 Paragraph 的模块集合。

演示 EPT 模块 滚动

滚动

9.7. 插件在 Drupal 中的使用。如何通过编程添加块。

17/10/2025, by Ivan

在本教程中,我们将学习如何通过自定义模块在 Drupal 8 中编程输出块。

代码示例可以在 GitHub 上查看:
https://github.com/levmyshkin/drupalbook8

首先,我们通过添加一个包含 PHP 类的文件开始,这是通过自定义模块在 Drupal 中创建块的方式。创建文件的过程与我们为页面所做的类相同,如我们之前所做的:

9.3. 创建一个自定义 Drupal 模块。编程输出页面。

我们只需要为插件创建一个文件:

modules/custom/drupalbook/src/Plugin/Block/FirstBlock.php

first block

现在让我们复制这段块代码,然后解析每一部分代码
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');
  }
}

block layout

我们将把块显示在 regina 左侧边栏或其他您方便的位置。

sidebar first

开始输入块的名称,Drupal 会自动提示您选择您的块。如果您的块没有出现,请检查代码是否在正确的文件中,并确保文件放置在正确的文件夹中,最后别忘了清除缓存。

place block

现在我们的块已经显示出来了,让我们看看添加块的代码是如何工作的:

my first block

文件开头是命名空间,用来确定我们的块插件文件应该放在哪里,以便 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;
进一步的注释是注解。我们不需要在 YML 文件中定义块,它会通过注解自动加载。

在这里,我们告诉 @block 它将是一个块插件。id 和 admin_label 将由 Drupal 自动获取,因此 id 必须是唯一的。@block 帮助通过 Drupal 管理面板翻译块标签。

extends BlockBase {

我们继承自 BlockBase 类,你可以按住 ctrl 并点击 PhpStorm 中的 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;
}

我们可以为每个通过编程创建的块使用单独的配置表单。如果你进入块的设置页面:

configure block

在这里,你可以看到我们在 blockForm() 方法中添加的 Name 字段:

configure block

我们使用 Drupal 表单 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