滚动
在 Drupal 模块中定义区块
第 V 部分,摘自 Drupal 8 基础模块构建实用教程
从 .info 到测试,仅涵盖基础知识
还记得在 本教程开头 我提到过我们将定义一个带表单的区块吗?现在正是处理它的时候。
/src/Form/LoremIpsumBlockForm.php
<?php namespace Drupal\loremipsum\Form; use Drupal\Core\Form\FormBase; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Url; /** * Lorem Ipsum 区块表单 */ class LoremIpsumBlockForm extends FormBase { /** * {@inheritdoc} */ public function getFormId() { return 'loremipsum_block_form'; }
这个文件和配置表单文件非常相似,不同的是它继承自 FormBase。
它同样有一个 buildForm() 方法,大致如下:
/** * {@inheritdoc} */ public function buildForm(array $form, FormStateInterface $form_state) { // 多少段落? $options = array_combine(range(1, 10), range(1, 10)); $form['paragraphs'] = [ '#type' => 'select', '#title' => $this->t('Paragraphs'), '#options' => $options, '#default_value' => 4, '#description' => $this->t('How many?'), ]; // 多少句子? $form['phrases'] = [ '#type' => 'textfield', '#title' => $this->t('Phrases'), '#default_value' => '20', '#description' => $this->t('Maximum per paragraph'), ]; // 提交按钮 $form['submit'] = [ '#type' => 'submit', '#value' => $this->t('Generate'), ]; return $form; }
这个方法用于在区块中放置表单,用户可以通过它来设置希望生成多少虚拟文本。
还需要添加 validateForm() 和 submitForm() 方法:
/** * {@inheritdoc} */ public function validateForm(array &$form, FormStateInterface $form_state) { $phrases = $form_state->getValue('phrases'); if (!is_numeric($phrases)) { $form_state->setErrorByName('phrases', $this->t('Please use a number.')); } if (floor($phrases) != $phrases) { $form_state->setErrorByName('phrases', $this->t('No decimals, please.')); } if ($phrases < 1) { $form_state->setErrorByName('phrases', $this->t('Please use a number greater than zero.')); } } /** * {@inheritdoc} */ public function submitForm(array &$form, FormStateInterface $form_state) { $form_state->setRedirect('loremipsum.generate', [ 'paragraphs' => $form_state->getValue('paragraphs'), 'phrases' => $form_state->getValue('phrases'), ]); } }
接下来是区块本身。
<?php namespace Drupal\loremipsum\Plugin\Block; use Drupal\Core\Access\AccessResult; use Drupal\Core\Block\BlockBase; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Session\AccountInterface; /** * 提供一个 Lorem ipsum 区块,可以在任意位置生成虚拟文本。 * * @Block( * id = "loremipsum_block", * admin_label = @Translation("Lorem ipsum block"), * ) */ class LoremIpsumBlock extends BlockBase { /** * {@inheritdoc} */ public function build() { // 返回 Form/LoremIpsumBlockForm.php 中定义的表单。 return \Drupal::formBuilder()->getForm('Drupal\loremipsum\Form\LoremIpsumBlockForm'); }
LoremIpsumBlock 类继承自 BlockBase,因此需要实现四个方法:build()、blockAccess()、blockForm() 和 blockSubmit()。第一个方法只是显示我们上一步定义的表单。
接着是访问控制:
/** * {@inheritdoc} */ protected function blockAccess(AccountInterface $account) { return AccessResult::allowedIfHasPermission($account, 'generate lorem ipsum'); }
为区块管理界面定义表单:
/** * {@inheritdoc} */ public function blockForm($form, FormStateInterface $form_state) { $form = parent::blockForm($form, $form_state); $config = $this->getConfiguration(); return $form; }
提交处理器:
/** * {@inheritdoc} */ public function blockSubmit($form, FormStateInterface $form_state) { $this->setConfigurationValue('loremipsum_block_settings', $form_state->getValue('loremipsum_block_settings')); } }
现在我们的区块应该可以正常工作了。