Blocks, Configuration, and Forms

drupal 8 中block系统由plugin API和entity API组成。也就是说即有可重用特性,又有fieldable特性。

Block最小化实现

  1. .info.yml
  2. src/Plugin/Block/ExampleEmptyBlock.php
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    /**
    * Provides a 'Example: empty block' block.
    *
    * @Block(
    * id = "example_empty",
    * admin_label = @Translation("Example: empty block")
    * )
    */
    class ExampleEmptyBlock extends BlockBase {
    /**
    * {@inheritdoc}
    */
    public function build() {
    // We return an empty array on purpose. The block will thus not be rendered
    // on the site. See BlockExampleTest::testBlockExampleBasic().
    return array('#markup' => t('empty block'));
    }
    }

练习

Create a block which displays a rotating banner of images.(Block configuration)

  1. .info.yml
  2. rotate_image_block.module

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    /**
    * Implements hook_theme().
    */
    function rotate_image_block_theme($existing, $type, $theme, $path) {
    return array(
    'rotate_image_block' => array(
    'variables' => array('image_path' => NULL),
    'template' => 'rotate-image-block',
    ),
    );
    }
  3. templates/rotate-image-block.html.twig

    1
    <img class="rotate" src="{{ image_path }}"/>
  4. src/Plugin/Block/RotateImageBlock.php

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    <?php
    namespace Drupal\rotate_image_block\Plugin\Block;
    use Drupal\Core\Block\BlockBase;
    use Drupal\Core\Form\FormStateInterface;
    use Drupal\file\Entity\File;
    /**
    * Provides a 'Example: configurable text string' block.
    *
    * Drupal\Core\Block\BlockBase gives us a very useful set of basic functionality
    * for this configurable block. We can just fill in a few of the blanks with
    * defaultConfiguration(), blockForm(), blockSubmit(), and build().
    *
    * @Block(
    * id = "rotate_image_block",
    * admin_label = @Translation("Rotate image")
    * )
    */
    class RotateImageBlock extends BlockBase {
    /**
    * {@inheritdoc}
    */
    public function blockForm($form, FormStateInterface $form_state) {
    $form['icon_upload'] = array(
    '#type' => 'managed_file',
    '#title' => $this->t('Icon image'),
    '#description' => $this->t('If you\'d like an image to display next to this menu item, upload it here.'),
    '#upload_validators' => array(
    'file_validate_extensions' => array('gif png jpg jpeg svg'),
    ),
    '#upload_location' => 'public://menu_icons/',
    '#default_value' => ["3"],
    );
    return $form;
    }
    /**
    * {@inheritdoc}
    */
    public function blockSubmit($form, FormStateInterface $form_state) {
    // First we just grab the file ID for the icon we uploaded, if any.
    $icon_field = $form_state->getValue('icon_upload');
    $file_id = empty($icon_field) ? FALSE : reset($icon_field);
    if (!empty($file_id)) {
    // Make this a permanent file so that cron doesn't delete it later.
    $file = File::load($file_id);
    $file->status = FILE_STATUS_PERMANENT;
    $file->save();
    // Grab the image's path for referencing it as a background image.
    $image_path = $file->getFileUri();
    $path = file_url_transform_relative(file_create_url($image_path));
    $this->configuration['image_path'] = $path;
    }
    }
    /**
    * {@inheritdoc}
    */
    public function build() {
    return array(
    '#theme' => 'rotate_image_block',
    '#image_path' => $this->configuration['image_path'],
    );
    }
    }

Create a form block which can send an e-mail to an address provided in the form. (block form)

  1. .info.yml
  2. src/Form/SimpleForm.php
    定义Form,用来输入email

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    public function buildForm(array $form, FormStateInterface $form_state) {
    $form['email'] = [
    '#type' => 'email',
    '#title' => $this->t('email'),
    '#description' => $this->t('Title must be a valid email address.'),
    '#required' => TRUE,
    ];
    // Group submit handlers in an actions element with a key of "actions" so
    // that it gets styled correctly, and so that other modules may add actions
    // to the form. This is not required, but is convention.
    $form['actions'] = [
    '#type' => 'actions',
    ];
    // Add a submit button that handles the submission of the form.
    $form['actions']['submit'] = [
    '#type' => 'submit',
    '#value' => $this->t('Submit'),
    ];
    return $form;
    }
    public function getFormId() {
    return 'send_email_block_simple_form';
    }
    public function submitForm(array &$form, FormStateInterface $form_state) {
    /*
    * This would normally be replaced by code that actually does something
    * with the title.
    */
    $email = $form_state->getValue('email');
    $newMail = \Drupal::service('plugin.manager.mail');
    $params['email'] = $email;
    $newMail->mail('send_email_block', 'send_email', $email, 'en', $params, $reply = NULL, $send = TRUE);
    drupal_set_message('Mail has been sent.', 'status');
    }
    }
  3. src/Plugin/Block/SendEmailBlock.php
    render SimpleForm到block

    1
    2
    3
    4
    public function build() {
    $form = \Drupal::formBuilder()->getForm('Drupal\send_email_block\Form\SimpleForm');
    return $form;
    }
  4. send_email_block.module
    实现hook_mail构建mail内容

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    function send_email_block_mail($key, &$message, $params) {
    // E-mail formatting will be exactly as below, so do not use indenting!
    $body =
    "Hi,
    I'm just showing off my work ...
    Works nicely huh?
    Should probably add a password here somewhere?
    Your username: " . $params['email'] . "
    See ya!";
    $message['subject'] = "Exercise account registration";
    $message['body'][] = Drupal\Core\Mail\MailFormatHelper::htmlToText($body);
    }

发送mail方法参照这里

参考资料

Blocks, Configuration, and Forms