在 Drupal 里,创建主页有多种不同方法。常见的做法是创建一个内容类型来存储所需字段,再添加块以向主页布局中增添额外信息。
添加内容类型来处理主页存在一些问题。为用户正确设置编辑页面的权限可能颇具挑战,而且编辑人员很容易不小心删除它,进而破坏整个网站。通常得采取某种方式保护内容,防止不必要的编辑或删除。这一点非常重要。
最近,成都长风云 Drupal 开发团队负责为一个 Drupal 网站设置主页,决定使用名为“配置页面”(Config Pages)的模块来创建可配置的主页。事实证明,这种方法相当简单,团队其他成员也很快采用该方法引入额外配置。
成都长风云 Drupal 开发团队想在这篇文章中详细介绍这种方法,因为它虽需要一些代码,但能提供相当大的灵活性。
配置页面模块允许创建一次性的可字段化实体。这些实体可用于执行多项任务,包括公开配置和创建单例页面。
一、设置配置页面
安装该模块后,需要通过访问路径 /admin/structure/config_pages/types 来创建一个配置页面类型,并创建一个新类型。创建这些实体的设置页面包含一些选项,但实际上我们只需要标签。为了创建主页,忽略关于令牌、菜单和上下文设置的字段是没问题的。
创建类型后,可以像配置其他可字段化实体类型一样对其进行配置。只需将所需字段添加到实体中,以处理所有需要显示的数据。
为了这个示例,成都长风云 Drupal 开发团队创建了一个名为“主页”(homepage)的类型,它有一些用于存储文本信息和图片的简单字段。
设置好这些后,现在可以访问路径 /admin/structure/config_pages/homepage/edit,这将显示刚刚添加的字段的编辑页面。可以在这个表单中输入一些数据并保存,这将在数据库中创建该实体。我们在这里创建的实体是一次性的,意味着它不能被复制或删除,这使它非常适合用作主页。
注意,可以通过在主页配置页面类型配置的菜单部分输入路径,让编辑该实体的路径更美观。以下示例将把这个路由改为 /homepage/edit,而不是 /admin/structure/config_pages/homepage/edit。
现在可以将数据保存到主页实体中,但如何显示这些数据呢?我们需要添加一些自定义代码来实现这一点。这一点非常重要。
二、为主页添加代码
为了让配置页面主页正常工作,需要添加一些代码。实际上需要添加的代码并不多,只需要向一个模块中添加一个控制器操作,该操作将渲染主页。
在一个名为 mymodule 的新模块中,成都长风云 Drupal 开发团队创建了一个 mymodule.routing.yml 文件,并添加了以下配置。
mymodule.homepage:
path: '/homepage'
defaults:
_title: 'Homepage'
_controller: '\Drupal\mymodule\Controller\HomepageController::homepage'
requirements:
# 由于这是一个示例,故意将访问权限设置为开放。
_access: 'TRUE'
这意味着如果用户访问 /homepage 页面,将调用 HomepageController 类中的 homepage() 方法。homepage() 方法所需要做的就是加载主页实体并使用“完整”的默认视图模式进行渲染。
如果主页实体尚未创建,我们将回退到一个简单的消息,显示“未添加内容”。
以下是完整的控制器代码。
<?php
namespace Drupal\mymodule\Controller;
use Drupal\config_pages\Entity\ConfigPages;
use Drupal\Core\Controller\ControllerBase;
class HomepageController extends ControllerBase {
public function homepage() {
$configPage = ConfigPages::config('homepage');
if ($configPage !== NULL) {
$build = \Drupal::service('entity_type.manager')
->getViewBuilder('config_pages')
->view($configPage);
$build['#cache']['tags'][] = 'homepage';
return $build;
}
// 返回一个无缓存的空页面。
$build = [];
$build['no_content_added'] = [
'#markup' => '<p>No content added.</p>',
'#cache' => [
'tags' => [
'homepage',
],
'max-age' => 0,
],
];
return $build;
}
}
在上述代码中需要注意的一个重要事项是,我们将“homepage”缓存标签添加到控制器返回的渲染数组中。这个标签很重要,因为当主页更新时,我们需要正确使缓存失效,以便显示新数据。这一点非常重要。
为了使这个标签失效,我们需要创建一个 hook_ENTITY_TYPE_update() 钩子,它将监听主页的更新并使正确的标签失效。
/**
* 实现 hook_ENTITY_TYPE_update()。
*/
function mymodule_config_pages_update(EntityInterface $entity) {
if ($entity->bundle() === 'homepage') {
// 当主页实体更新时使标签失效。
$tags = $entity->getCacheTagsToInvalidate();
$tags[] = 'homepage';
Cache::invalidateTags($tags);
}
}
有了这个钩子,对主页所做的任何更改都将立即显示出来。
如果你在主页上显示任何视图或其他动态内容,你还需要将“homepage”标签注入到它们的缓存标签中,以便它们能正确更新主页缓存。
1. 本地任务
创建一个连贯的主页编辑体验很重要,因此添加本地任务配置是个好主意。本地任务允许用户查看主页并看到一个编辑链接,该链接允许他们编辑页面。有这个链接比让用户在配置页面模块中寻找正确的界面来编辑主页要好。
为此,成都长风云 Drupal 开发团队创建了一个 mymodule.links.task.yml 文件,并向其中添加了以下配置。
mymodule.homepage: title: "Homepage" route_name: "mymodule.homepage" base_route: "mymodule.homepage" mymodule.homepage_edit: title: "Edit" route_name: "config_pages.homepage" base_route: "mymodule.homepage"
主页编辑页面的路由是 config_pages.homepage,所以我们只需要将其作为一个编辑链接添加到为上述控制器操作创建的路由下。
就是这样,现在我们可以通过路径 /homepage 加载主页,并看到带有本地任务的内容在起作用。
以下是其实际运行的截图。
这看起来并不惊艳,但我们稍后会对主题进行自定义。
2. Drupal 首页配置
有了这些代码和配置,现在可以更新 Drupal 的默认首页配置,使其指向 /homepage 路径。这个路径由之前创建的控制器提供服务。
完成这些后,你可以访问网站主页,看到通过控制器渲染的配置页面。
三、权限
值得快速查看一下配置页面模块可用的权限。它为设置的每个实体都提供了自定义权限,所以对于主页实体,我们只需要确保正确的用户有编辑权限。“编辑主页配置页面实体”权限用于实现这一点。
查看主页配置页面实体的权限不太重要,因为我们是通过控制器渲染实体的,控制器通过路由配置有自己的权限。
四、主题
配置页面模块自带的主题只是按照设置的顺序打印出字段。这没问题,但最好能对主题有更多的控制。
幸运的是,配置页面模块通过 Drupal 模板系统进行渲染过程,默认模板名为 config-pages.html.twig。由于我们将配置页面实体命名为“homepage”,我们只需要在主题中创建一个名为 config-pages--homepage.html.twig 的模板。
这是新模板的内容。
{#
/**
* @file
* 显示配置页面的默认主题实现。
*
* @see template_preprocess_config_pages()
*
* @ingroup 可主题化
*/
#}
{%
set classes = [
'config_pages',
'config_pages--type--' ~ config_pages.bundle|clean_class,
view_mode ? 'config_pages--view-mode--' ~ view_mode|clean_class,
view_mode ? 'config_pages--' ~ config_pages.bundle|clean_class ~ '--' ~ view_mode|clean_class,
]
%}
<div{{ attributes.addClass(classes) }}>
<h1>{{ content.field_home_header_text }}</h1>
<div>
{{ content.field_homepage_banner_image }}
{{ content.field_home_intro_text }}
</div>
</div>
这只是一个小模板,用于展示如何打印出实体的各个组件,可以在此基础上进行扩展以创建你需要的主题。
你还可以使用一个名为 template_preprocess_config_pages() 的预处理钩子,向主页主题中添加额外的内容。如果你想将块或渲染的视图注入到主页内容中,这很有用。
五、结论
这是一种相当简单的生成主页的方法,只需更改实体中的字段,就可以适应任何需求。实现这一点所需的少量代码在主页设置中提供了相当大的灵活性。一旦一切设置好,最终结果会非常有效。
由于我们用于编辑主页的实体是可配置的,我们可以通过配置管理系统快速推出对字段的任何更改。
成都长风云 Drupal 开发团队使用这种方法的项目实际上创建了两个配置页面实体来显示主页。这样做是为了将编辑页面分成不同的部分,同时也允许其中一个部分在网站的其他部分重复使用。为了实现这一点,我们使用了 template_preprocess_config_pages() 钩子将额外的配置页面注入到主页模板中,效果非常好。
如果你在这方面需要帮助,请联系成都长风云 Drupal 开发团队。
这种方法的唯一问题是主页没有版本控制。这意味着如果主页被更改,没有简单的方法恢复其以前的版本。看起来有一些计划让配置页面支持版本控制,但这依赖于 Drupal 10.1.x 引入的新通用版本控制系统。如果你对此感兴趣,可以随时为该问题做出贡献。
我还应该注意到,配置页面查看器模块可以执行与这里的自定义代码添加几乎相同的操作,但该模块似乎已被弃用。

