跳转到主要内容

主页内容

Drupal模块开发之module_name.routing.yml文件详述

由 webadmin 发布于 阅读 34 次

1、简介

.routing.yml文件用于定义模块的路由。路由系统在 Drupal 中非常重要,它决定了当用户访问特定的 URL 时,应该执行哪些代码,并返回哪些内容。

.routing.yml 文件中,可以定义一系列的路由。每个路由都有一个名字,以及一些属性,包括:

path:定义路由的 URL。例如,/my-module/my-page。
defaults:定义当这个路由被匹配时,应该执行哪些代码。这里一般会指定一个控制器类和一个方法,这个方法会生成并返回页面的内容。
requirements:定义一些条件,只有当这些条件满足时,路由才会被匹配。例如,可以指定用户必须有某个权限,才能访问这个路由。

options:在 Drupal 路由系统中定义了一些附加的路由配置。以下是一些常见的选项:

parameters: 用于定义 URL 中动态参数的转换规则。例如,你可以定义一个参数转换器,将 URL 中的用户 ID 转换为用户对象。

no_cache: 如果设置为 TRUE,Drupal 将不会缓存这个路由的响应。

_admin_route: 如果设置为 TRUE,Drupal 会将这个路由视为管理员路由,应用管理员主题。

_legacy: 如果设置为 TRUE,Drupal 不会在这个路由上应用 Symfony 的路由匹配逻辑。

_theme: 用于指定这个路由应该使用的主题。

compiler_class: 用于指定这个路由的编译器类。

compiler_options: 用于指定传递给路由编译器的选项。

utf8:如果设置为 TRUE,Drupal 将允许在 URL 中使用 UTF-8 字符。

例如:

module_name.my_page:
  path: '/my-module/my-page'
  defaults:
    _controller: '\Drupal\module_name\Controller\MyController::myPage'
    _title: 'My Page'
 options:
    no_cache: 'TRUE'
  requirements:
    _permission: 'access content'

上面的代码定义了一个名为 module_name.my_page 的路由。当用户访问 /my-module/my-page URL 时,Drupal 会执行 MyController 类中的 myPage 方法,并显示返回的内容。用户需要有 "access content" 权限才能访问这个页面。

2、defaults配置项

demo_ajax.admin.settings:
  path: '/admin/demo_ajax/settings'
  defaults:
    _controller: '\Drupal\system\Controller\SystemController::systemAdminMenuBlockPage'
    _title: '这是一个配置页面'
  requirements:
    _permission: 'administer themes pages site configuration'
demo_ajax.admin_setting2:
  path: '/admin/demo_ajax/settings/config'
  defaults:
    _form: '\Drupal\demo_ajax\Form\ModuleConfigurationForm'
    _title: '这是配置项表单页面'
  requirements:
    _permission: 'administer site configuration'

可以看到上例中defaults配置项下有两种配置写法,一个是_controller一个是_form两种写法的主要区别在于它们指定的处理请求的方式不同:

_form: '\Drupal\demo_ajax\Form\ModuleConfigurationForm':这个配置指定了一个表单类 ModuleConfigurationForm 来处理请求。在这个表单类中,可以定义表单的结构,包括表单中的字段、验证规则、以及当表单提交时应该执行的操作。当用户访问这个路由时,Drupal 会显示这个表单,并处理用户的输入。

_controller: '\Drupal\system\Controller\SystemController::SystemAdminMenuBlockPage':这个配置指定了一个控制器类 SystemController 和一个方法 SystemAdminMenuBlockPage 来处理请求。当用户访问这个路由时,Drupal 会执行这个方法,并将方法的返回值作为页面的内容。这种方式比表单类更灵活,你可以在方法中执行任何你需要的代码,包括查询数据库、处理数据、或者生成复杂的 HTML 结构。

当需要处理用户输入的表单,应该使用 _form 配置。如果需要执行更复杂的逻辑,或者生成复杂的页面内容,应该使用 _controller 配置。

3、defaults选项配置实例

3.1、创建一个模块配置项列表页面

以上面的例子为基础,创建一个模块的配置列表页面。路由为:demo_ajax.admin.settingsSystemControllerSystem 模块的控制器类,SystemAdminMenuBlockPage 是这个类中的一个方法。这个方法的作用是生成系统管理菜单的页面。

3.2、创建一个表单页面用来配置模块的一些参数

配置项_form: '\Drupal\demo_ajax\Form\ModuleConfigurationForm'指向了我的模块目录下的ModuleConfigurationForm类,在这个类中创建了一个表单,用来配置模块所需的一些参数。

ModuleConfigurationForm类的完整代码如下:

<?php
namespace Drupal\demo_ajax\Form;
use Drupal\Core\Form\ConfigFormBase;
use Drupal\Core\Form\FormStateInterface;
/**
 * Defines a form that configures forms module settings.
 */
class ModuleConfigurationForm extends ConfigFormBase {
  /**
   * {@inheritdoc}
   */
  public function getFormId() {
    return 'demo_ajax_admin_settings';
  }
  /**
   * {@inheritdoc}
   */
  protected function getEditableConfigNames() {
    return [
      'demo_ajax.settings',
    ];
  }
  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {
    $config = $this->config('demo_ajax.settings');
    $form['username'] = [
      '#type' => 'textfield',
      '#title' => $this->t('User Name'),
      '#default_value' => $config->get('username'),
    ];
    $form['password'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Password'),
      '#default_value' => $config->get('password'),
    ];
    $form['email'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Email'),
      '#default_value' => $config->get('email'),
    ];
    $form['age'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Age'),
      '#default_value' => $config->get('age'),
    ];
    $form['gender'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Gender'),
      '#default_value' => $config->get('gender'),
    ];
    return parent::buildForm($form, $form_state);
  }
  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    $this->config('demo_ajax.settings')
      ->set('username', $form_state->getValue('username'))
      ->set('password', $form_state->getValue('password'))
      ->set('email', $form_state->getValue('email'))
      ->set('age', $form_state->getValue('age'))
      ->set('gender', $form_state->getValue('gender'))
      ->save();
    parent::submitForm($form, $form_state);
  }
}

获取配置项的值:

$config = \Drupal::config('demo_ajax.settings'); 
$username = $config->get('username'); 
$password = $config->get('password'); 
$email = $config->get('email'); 
$age = $config->get('age');
......

4、配置路由参数

功能目标:获取所有用户,以表格形式显示结果,可以查看用户资料、可以删除用户。

(1)、新建一个DemoUserController.php

<?php
namespace Drupal\demo_ajax\Controller;

//引入 ControllerBase 类,它是 Drupal 控制器的基类。
//在创建一个新的控制器的时候需要继承这个类,因为它提供了许多有用的方法和服务。
use Drupal\Core\Controller\ControllerBase;
//引入 EntityTypeManagerInterface 接口。这个接口定义了一些用于管理和操作实体类型的方法。
//在 Drupal 中,实体类型是用于存储和管理数据的主要方式,例如用户、节点(内容)和术语等。
use Drupal\Core\Entity\EntityTypeManagerInterface;
//引入 ContainerInterface 接口,它是 Symfony 依赖注入容器的接口。
//在 Drupal 中,依赖注入容器用于管理和提供服务。如果你需要在你的类中使用服务(例如数据库连接、配置管理等)。
use Symfony\Component\DependencyInjection\ContainerInterface;
//引入 Url 类,它是 Drupal 的一个服务,用于生成和处理 URL,这个类的 fromRoute 方法来生成链接的 URL。
use Drupal\Core\Url;
//
use Drupal\Core\Messenger\MessengerInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;

class DemoUserController extends ControllerBase {

  protected $entityTypeManager;

  public function __construct(EntityTypeManagerInterface $entityTypeManager, MessengerInterface $messenger) {
    $this->entityTypeManager = $entityTypeManager;
    $this->messenger = $messenger;
  }

  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('entity_type.manager'),
      $container->get('messenger')
    );
  }

  /**
   * 获取所有用户并渲染成表格输出
   * @return array
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   */
  public function get_users() {
    //从实体类型管理器中获取用户实体的存储。'user' 是 Drupal 中用户实体的机器名称。
    //实体类型管理器是 Drupal 的服务,用于处理各种实体类型,例如用户、节点、术语等。
    $user_storage = $this->entityTypeManager->getStorage('user');

    //用户实体的存储中获取查询对象,用于构建对用户实体的查询。
    $query = $user_storage->getQuery();

    //向查询添加了一个条件,要求用户 ID('uid')大于 0。
    //在 Drupal 中,匿名用户的 ID 是 0,所以这个条件的效果是排除匿名用户。
    $query->condition('uid', 0, '>');

    //禁用查询的访问检查。默认情况下,Drupal 的实体查询会检查当前用户是否有权限查看每个实体。
    //通过设置 accessCheck(false),查询将返回所有匹配的实体,无论当前用户是否有权限查看它们。
    $query->accessCheck(false);

    //执行查询并返回用户 ID 的数组。每个元素都是一个用户 ID。
    $uids = $query->execute();

    //从用户实体的存储中加载多个用户。参数是一个用户 ID 的数组,返回值是一个用户实体的数组,
    //数组的键是用户 ID,数组的值是用户实体对象。
    $users = $user_storage->loadMultiple($uids);

    //定义了一个 Drupal 表格的表头。每个键值对定义了一个表头单元格,键是字段的机器名称,值是字段的标签。
    $header = [
      'uid' => $this->t('User ID'),
      'name' => $this->t('Username'),
      'mail' => $this->t('Email'),
      'created' => $this->t('Created Time'),
      'OPERATIONS' => $this->t('OPERATIONS'),
    ];

    $rows = [];
    foreach ($users as $user) {
      $rows[] = [
        'uid' => $user->id(),//用户的id
        'name' => $user->getAccountName(),//用户的username
        'mail' => $user->getEmail(),//用户的邮箱
        'created' => date('Y-m-d',$user->getCreatedTime()),//用户创建的时间
        //在 Drupal 表格的每一行创建一个包含 "View" 和 "Delete" 两个操作链接的下拉按钮。
        //创建一个名为 "actions" 的列,该列包含一个下拉按钮(dropbutton)。下拉按钮有两个链接,分别是 "View" 和 "Delete"。
        'actions' => [
          'data' => [//定义了这个列的内容。在这个例子中,内容是一个下拉按钮。
            '#type' => 'dropbutton',//定义了元素的类型为下拉按钮
            '#links' => [//定义了下拉按钮的链接。
              'show' => [
                'title' => $this->t('View'),//定义了链接的标题,即显示给用户的文本。
                //view按钮的链接和参数 uid
                'url' => Url::fromRoute('demo_ajax.get_user_info', ['uid' => $user->id()]),
              ],
              'delete' => [
                'title' => $this->t('Delete'),
                //delete按钮的链接和参数 uid
                'url' => Url::fromRoute('demo_ajax.delete', ['uid' => $user->id()]),
              ],
            ],
          ],
        ],
      ];
    }

    $build['user_table'] = [//定义了一个名为 "user_table" 的表格元素
      '#type' => 'table',//定义了元素的类型为表格。
      '#header' => $header,//定义了表格的头部。
      '#rows' => $rows,//定义了表格的行
      '#empty' => $this->t('No users found'),//定义了当表格没有行时显示的消息
    ];

    return $build;
  }

  /**
   * @param $uid
   * 获取用户信息
   * @return array|string[]
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   */
  public function get_user_info( $uid ){
    $user_storage = $this->entityTypeManager->getStorage('user');
    //$user_storage->load($uid):获取一个用户的资料,如果找到了对应的实体,它会返回一个实体对象;如果没有找到,它会返回 NULL
    $user = $user_storage->load($uid);
    if ($user) {
      return $this->formBuilder()->getForm('Drupal\demo_ajax\Form\UserProfileForm', $user);
    }else {
      return [
        '#type' => 'markup',
        '#markup' => '用户不存在~',
      ];
    }
  }

  /**
   * @param $uid
   * 删除用户
   * @return array|\Symfony\Component\HttpFoundation\RedirectResponse
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   */
  public function delete_user( $uid ){
    $user_storage = $this->entityTypeManager->getStorage('user');
    $user = $user_storage->load($uid);
    if ($user){
      try {
        $user->delete();//彻底删除用户
        $this->messenger->addMessage($this->t('ID = '.$uid.'的用户已经被删除.'));
        // 获取上一页面的 URL
        $referer = \Drupal::request()->headers->get('referer');
        //当一个用户被删除成功后,跳转回上一页(用户列表页)
        return new RedirectResponse($referer);
      } catch (\Drupal\Core\Entity\EntityStorageException $e) {
        $this->messenger->addError($this->t('发生错误,无法删除用户。'));
        \Drupal::logger('demo_ajax')->error($e->getMessage());
        return [
          '#type' => 'markup',
          '#markup' => $this->t('发生错误,无法删除用户。'),
        ];
      }
    }else{
      $this->messenger->addError($this->t('用户不存在.'));
      return [
        '#type' => 'markup',
        '#markup' => $this->t('用户不存在'),
      ];
    }

  }

}

(2)、定义路由,路由地址中包含要传递的参数,用户id(uid):

#获取用户列表的路由
demo_ajax.get_users:
  path: '/admin/demo_ajax/get_users'
  defaults:
    _controller: '\Drupal\demo_ajax\Controller\DemoUserController::get_users'
    _title: '测试获取用户列表'
  requirements:
    _permission: 'administer site configuration'
#查看某个用户的详细资料
demo_ajax.get_user_info:
  path: '/admin/demo_ajax/get_user_info/{uid}'
  defaults:
    _controller: '\Drupal\demo_ajax\Controller\DemoUserController::get_user_info'
    _title: '测试获取用户信息'
  requirements:
    _permission: 'administer site configuration'
#删除某个用户
demo_ajax.delete:
  path: '/admin/demo_ajax/delete_user/{uid}'
  defaults:
    _controller: '\Drupal\demo_ajax\Controller\DemoUserController::delete_user'
    _title: '删除用户'
  requirements:
    _permission: 'administer site configuration'

进入:/admin/demo_ajax/get_users

点击【view】按钮后,进入用户资料页面:

UserProfileForm.php代码如下:

<?php


namespace Drupal\demo_ajax\Form;

use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;

class UserProfileForm extends FormBase {

  public function getFormId() {
    return 'user_profile_form';
  }

  public function buildForm(array $form, FormStateInterface $form_state, $user = NULL) {
    $form['name'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Username'),
      '#default_value' => $user->get('name')->value,
      '#disabled' => TRUE,
    ];

    $form['mail'] = [
      '#type' => 'email',
      '#title' => $this->t('Email address'),
      '#default_value' => $user->get('mail')->value,
      '#disabled' => TRUE,
    ];

    return $form;
  }

  public function submitForm(array &$form, FormStateInterface $form_state) {
    //表单提交操作
  }

}