Drupal 8 services

一个service是一个Service Container(Service容器, 包含所有Service,也可以叫Service的统一管理器)的实例化对象. 用于重复的操作和使用. 就好比面向过程写法中的函数封装. 那为什么不使用普通类而是使用Service呢?

  • 依耐注入
  • 方便管理
  • 支持Tagged

获取Service
$server = \Drupal::services(‘your_service_sname’);

控制器注入Services

namespace Drupal\mymodule\Controller;

use Drupal\Core\Controller\ControllerBase;

class MymoduleController extends ControllerBase {

  protected $dateFormatter;

  /**
   * 初始化的时候将service: date.formatter注入.
   *
   * @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter
   *   The date formatter service.
   */
  public function __construct(DateFormatterInterface $date_formatter) {
    $this->dateFormatter = $date_formatter;
  }

  /**
   * 这里是初始化__construct的参数. create函数会接收Service Container参数.然后获取你需要的service作为参数.
   *
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('date.formatter')
    );
  }
}

举例为什么使用Service

这边我们有一个需求,可以根据一个类管理器来获取所有类,而且自动调用,不用去new。可以自动传参数. 或者动态获取参数

此处有一个类. 负责打印一个$name

class A {
  public $name;
  public function __construct($name) {
    $this->name = $name;
  }

  public function printName() {
    print $this->name;
  }
}

如果想使用很简单. 我们要打印的是$_SESSION里面的name.

$a = new A($_SESSION['name']);
$a->printName();

现在我们要做一个类管理器. 这个类管理器负责获取和管理所有类

class StaticContainer {
  public static function get($class_name) {
    return new $class_name();
  }
}

StaticContainer::get('A')->printName();

但是这样会报错,所以我们需要一个配置,让传默认参数.

session_start();
$_SESSION['name'] = 'xiukun';


class A {
  public $name;
  public function __construct($name) {
    $this->name = $name;
  }

  public function printName() {
    print $this->name;
  }
}

class B {

}

// 这里就像我们service就的配置
function classConfig() {
  return [
    'A' => [
      'class_name' => 'A',
      'arguments' => [$_SESSION['name']]
    ],
    'B' => [
      'class_name' => 'B'
    ]
  ];
}

class StaticContainer {
  private static $classConfig;
  public static function get($class_name) {
    if(!isset(self::$classConfig)) {
      self::$classConfig = classConfig();
    }

    if (isset(self::$classConfig[$class_name])) {
      $cname = self::$classConfig[$class_name]['class_name'];
      $args = isset(self::$classConfig[$class_name]['arguments']) ?
        self::$classConfig[$class_name]['arguments'] : [];

      return (new ReflectionClass ($cname))->newInstanceArgs($args);
    }
  }
}

StaticContainer::get('A')->printName();

这样不管在哪静态调用都能自动传参数