Drupal 9 Services

By admin, 5 一月, 2022

Drupal 9的设计大量依赖于service。sevices的核心是让依赖的逻辑写在初始化阶段,这样可以让实际逻辑大大简化,并且可维护性更好。所有\Drupal的写法都是Drupal对面向过程写法的兼容,被视为违反设计模式。不确定会不会在后续Drupal版本(例如Drupal 10)里不能用。下面是一个在Form里如何用Drupal 9 service的方式实现\Drupal::configFactory()功能的例子。就单一功能来说,例子的写法似乎更复杂了。但就整个复杂的系统来说,这样做是简化了,当我们熟悉了初始化service的方式,那些初始化的代码基本都是复制粘贴的。

1. FormBase和ControllerBase子类引入service的方法

<?php

namespace Drupal\utility\Form\SystemConsole\ConfigForm;

use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\utility\System\System;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Config\ConfigFactoryInterface;


final class LoginConfig extends FormBase {
  /**
   * The config factory object.
   *
   * @var \Drupal\Core\Config\ConfigFactoryInterface
   */
  protected $configFactory;

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('config.factory')
    );
  }

  /**
   * Constructs a ExampleController object.
   *
   * @param \Drupal\Core\Config\ConfigFactoryInterface $configFactory
   *   A configuration factory instance.
   */
  public function __construct(ConfigFactoryInterface $configFactory) {
    $this->configFactory = $configFactory;
  }

  /**
   * {@inheritdoc}
   */
  public function getFormId() {
    return 'utility_system_login_config';
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {

    $form['user_login_error_limit'] = [
      '#type' => 'textfield',
      '#title' => '用户登录失败次数限制',
      '#description' => '(用户尝试登录失败次数超过限制次数时,将被限制登录)',
      '#default_value' => $this->configFactory->getEditable('user.flood')->get('user_limit'),
    ];

    $form['save'] = [
      '#type' => 'submit',
      '#value' => '保存',
    ];


    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
      $messenger = $this->messenger();

      $user_limit = $form_state->getValue('user_login_error_limit');
      $this->configFactory->getEditable('user.flood')->set('user_limit', $user_limit)->save();

      $messenger->addStatus('保存成功');

  }

}

事实上,configFactory是FormBase的属性,在FormBase子类里无法再实现,调用$this->configFactory()即可获得该服务引用对象。

2. 定义自己的service

如果我们的类不是FormBase或ControllerBase的子类,而类里面需要调用service。那么我们可以在example.services.yml里声明自己的service。

 

services:

  utility.zip:
    class: Drupal\utility\Component\Zip\ZipMarker
    arguments: ['@current_user', '@file_system', '@messenger']

然后在构造方法里给依赖的服务初始化:

  public function __construct(AccountInterface $currentUser, FileSystemInterface $fileSystem, MessengerInterface $messenger) {
    $this->user = $currentUser;
    $this->fileSystem = $fileSystem;
    $this->messenger = $messenger;
  }

调用的时候很方便,连use都不用:

    $zipMaker = \Drupal::service('utility.zip');
 

 

 

这里有另外一篇笔记进一步探讨服务、容器、依赖设计模式:https://cto.eguidedog.net/node/1199

参考:

标签

评论

Restricted HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id> <img src>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。
验证码
This question is for testing whether or not you are a human visitor and to prevent automated spam submissions.
请输入"Drupal10"