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.settings,SystemController 是 System 模块的控制器类,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) {
//表单提交操作
}
}