在Drupal 8中创建自定义字段格式化程序

tech2022-09-04  100

Please be aware that due to the development process Drupal 8 has been undergoing at the time of writing, some parts of the code might be outdated. Take a look at this repository in which I try to update the example code and make it work with the latest Drupal 8 release.

请注意,由于在编写本文时Drupal 8正在进行开发过程,因此某些代码部分可能已过时。 看看这个存储库 ,我尝试在其中更新示例代码并使之与最新的Drupal 8版本一起使用。

With the introduction of annotated plugins, a lot has changed in Drupal 8. We have a more streamlined approach to describing and discovering pieces of functionality that extend the core. Along with many other components, the former Field API (part of the larger and consolidated Entity API) is now based on plugins.

随着带注释的插件的引入,Drupal 8发生了很多变化。我们有一种更简化的方法来描述和发现扩展核心的功能。 与许多其他组件一起,以前的Field API(较大和合并的Entity API的一部分)现在基于插件。

In this tutorial we will go through defining a custom field formatter for an existing field (image). What we want to achieve is to make it possible to display an image with a small caption below it. This caption will be the title value assigned to the image if one exists.

在本教程中,我们将为现有字段(图像)定义自定义字段格式化程序。 我们要实现的是使显示在其下方带有小标题的图像成为可能。 该标题将是分配给图像的title值(如果存在)。

The code we write here can be found in this repository as the image_title_caption module. But let’s see how we can get to that final result.

我们在此处编写的代码可以在该存储库中找到,作为image_title_caption模块。 但是,让我们看看如何获​​得最终结果。

Drupal模块 (The Drupal module)

Let us start by creating a new custom module (image_title_caption) with only one file:

让我们首先创建一个仅包含一个文件的新自定义模块( image_title_caption ):

image_title_caption.info.yml:

image_title_caption.info.yml :

name: Image title caption type: module description: Uses the image title field as a caption core: 8.x dependencies: - image

Nothing out of the ordinary here. We can even enable the module already if we want.

这里没有什么不寻常的。 如果需要,我们甚至可以启用该模块。

插件 (The plugin)

In Drupal 8, field formatters (like field types and widgets themselves) are plugins. Core ones are defined either by core modules or can be found inside the Drupal\Core\Field\Plugin\Field\FieldFormatter namespace. And like we’ve seen in a previous article in which we looked at custom blocks, plugins go inside the src/Plugin/ folder of our module. In the case of field formatters, this will be src/Plugin/Field/FieldFormatter directory.

在Drupal 8中,字段格式化程序(如字段类型和窗口小部件本身)是插件。 核心模块由核心模块定义,或者可以在Drupal\Core\Field\Plugin\Field\FieldFormatter命名空间中找到。 就像我们在上一篇文章中看到的自定义块一样 ,插件位于模块的src/Plugin/文件夹中。 对于字段格式化程序,这将是src/Plugin/Field/FieldFormatter目录。

Below you can see our own formatter class:

在下面,您可以看到我们自己的格式化程序类:

src/Plugin/Field/FieldFormatter/ImageTitleCaption.php:

src / Plugin / Field / FieldFormatter / ImageTitleCaption.php :

<?php /** * @file * Contains \Drupal\image_title_caption\Plugin\Field\FieldFormatter\ImageTitleCaption. */ namespace Drupal\image_title_caption\Plugin\Field\FieldFormatter; use Drupal\Core\Field\FieldItemListInterface; use Drupal\image\Plugin\Field\FieldFormatter\ImageFormatter; /** * Plugin implementation of the 'image_title_caption' formatter. * * @FieldFormatter( * id = "image_title_caption", * label = @Translation("Image with caption from title"), * field_types = { * "image" * } * ) */ class ImageTitleCaption extends ImageFormatter { /** * {@inheritdoc} */ public function viewElements(FieldItemListInterface $items) { $elements = parent::viewElements($items); foreach ($elements as &$element) { $element['#theme'] = 'image_title_caption_formatter'; } return $elements; } }

This is our plugin. Nothing else to it. Above the class declaration we have the @FieldFormatter annotation through which the plugin gets discovered. We specify a plugin ID (image_title_caption), label and an array of field types this formatter can be used with. In our case, the latter only contains the default image field type but we could support more if we wanted to, even custom field types. The values that go in that array are plugin IDs so if you look at the image field type plugin, you’ll see that its ID is image.

这是我们的插件。 没有别的了。 在类声明上方,我们具有@FieldFormatter批注,通过它可以发现插件。 我们指定一个插件ID( image_title_caption ),标签和该格式化程序可以使用的字段类型数组。 在我们的情况下,后者仅包含默认的image字段类型,但如果需要,我们甚至可以支持自定义字段类型。 该数组中包含的值是插件ID,因此,如果查看image字段类型plugin ,则会看到其ID为image 。

The class looks simple because we are extending from the default ImageFormatter plugin defined by the core Image module. For our purpose, all we need to override is the viewElements() method which is responsible for returning a render array of our field data. The latter can be found inside the $items list and can be used and prepared for rendering.

该类看起来很简单,因为我们是从核心Image模块定义的默认ImageFormatter插件扩展而来的。 为了我们的目的,我们需要重写的是viewElements()方法,该方法负责返回字段数据的渲染数组。 后者可以在$items列表中找到,并且可以用于渲染。

The first thing we do in this method is make sure we call the parent class method on the items and store that in a variable. That will already prepare the image to be rendered just as if it would normally.

我们在此方法中所做的第一件事是确保对项目调用父类方法并将其存储在变量中。 这将已经准备好要正常渲染的图像。

By default, the ImageFormatter plugin (the parent) uses the image_formatter theme inside the render array to output the image field values. What we do here is that for each item, we replace this theme with our own: image_title_caption_formatter. Then we return the elements (render array) just like the parent does.

默认情况下, ImageFormatter插件(父级)使用render数组内的image_formatter主题输出图像字段值。 我们在这里所做的是,对于每个项目,我们将其替换为我们自己的主题: image_title_caption_formatter 。 然后像父对象一样返回元素(渲染数组)。

You’ll notice this a lot in Drupal 8: we get a very good indication on what we need to do from the parent classes we extend. And if you ask me, that is much better than figuring out what some magic hook or function does.

您会在Drupal 8中注意到很多:我们从扩展的父类中很好地表明了我们需要做什么。 如果您问我,那比弄清楚某些魔术钩子或函数的作用要好得多。

主题 (The theme)

Since the image_title_caption_formatter theme we specified above is so far imaginary, we’ll need to create it. Inside the .module file of our module we need to implement hook_theme:

由于我们上面指定的image_title_caption_formatter主题到目前为止是虚构的,因此需要创建它。 在我们模块的.module文件中,我们需要实现hook_theme :

image_title_caption.module:

image_title_caption.module :

/** * Implements hook_theme(). */ function image_title_caption_theme() { return array( 'image_title_caption_formatter' => array( 'variables' => array('item' => NULL, 'item_attributes' => NULL, 'url' => NULL, 'image_style' => NULL), ), ); }

This should look familiar as it is very similar to Drupal 7. Please take note of the variables we pass to this theme. We intend to override the default image_formatter theme so we should have the same variables passed here as well. Additionally, since the image_formatter theme is preprocessed, we’ll need to create a preprocessor for our theme as well:

这看起来很熟悉,因为它与Drupal 7非常相似。请注意我们传递给该主题的变量。 我们打算覆盖默认的image_formatter主题,因此我们也应该在此处传递相同的变量。 此外,由于image_formatter主题已经过预处理,因此我们还需要image_formatter主题创建一个预处理器:

/** * Implements template_preprocess_image_title_caption_formatter(). */ function template_preprocess_image_title_caption_formatter(&$vars) { template_preprocess_image_formatter($vars); $vars['caption'] = String::checkPlain($vars['item']->get('title')->getValue()); }

In this preprocessor we perform two actions:

在此预处理器中,我们执行两个操作:

We make sure that the variables passed to the template file will have first been preprocessed by the default image_formatter theme preprocessor. This is so that all the variables are exactly the same and the image gets displayed as it normally would be.

我们确保传递给模板文件的变量将首先由默认的image_formatter主题预处理器进行预处理。 这样,所有变量都完全相同,并且可以正常显示图像。

We create a new variable called caption that will contain the sanitised value of the image title.

我们创建一个名为caption的新变量,其中将包含图像标题的已清理值。

For sanitisation, we use the helper String class statically. We are still inside the .module file so we cannot inject it, but we need to use it at the top of the file:

为了卫生起见,我们静态地使用Helper String类。 我们仍然位于.module文件中,因此我们无法注入它,但需要在文件顶部使用它:

use Drupal\Component\Utility\String;

模板 (Template)

Lastly, we need to create a template file for our new theme:

最后,我们需要为我们的新主题创建一个模板文件:

templates/image-title-caption-formatter.html.twig:

templates / image-title-caption-formatter.html.twig :

{% if url %} <a href="{{ url }}">{{ image }}</a> {% else %} {{ image }} {% endif %} {% if caption %} <div class="image-caption">{{ caption }}</div> {% endif %}

Similar to Drupal 7, the name of this file is important as it mirrors the theme name. As for the contents, they are almost the same as the template used by the image_formatter theme except for the caption printed at the bottom.

与Drupal 7相似,此文件的名称很重要,因为它反映了主题名称。 至于内容,除了底部显示的标题外,它们与image_formatter主题所使用的模板几乎相同。

它行得通吗? (Does it work?)

Now that we’ve written the code, we need enable the module and clear all the caches if we had made code changes after enabling. It’s time to test it out.

现在,我们已经编写了代码,如果启用后对代码进行了更改,则需要启用模块并清除所有缓存。 现在该进行测试了。

For example, go to the article content type field display settings at admin/structure/types/manage/article/display. For the Image field, under the Format heading, you should be able to select the Image with caption from title format. Save the form and go to admin/structure/types/manage/article/fields/node.article.field_image and make sure the image field title is enabled.

例如,转到admin/structure/types/manage/article/display的文章内容类型字段显示设置。 对于“图像”字段,在“ Format标题下,您应该能够Image with caption from title格式中选择Image with caption from title的Image with caption from title 。 保存表单,然后转到admin/structure/types/manage/article/fields/node.article.field_image并确保已启用图像字段标题。

Finally, you can edit an article, upload an image and specify a title. That title will continue to behave as such, but additionally, it will be displayed below the image as a caption. Of course, you can still style it as you wish etc.

最后,您可以编辑文章,上传图像并指定标题。 该标题将继续保持原样,但此外,它将作为标题显示在图像下方。 当然,您仍然可以根据需要设置样式。

结论 (Conclusion)

In this article we’ve seen how easy it is to create a field formatter and extend default behaviour in Drupal 8. We’ve only touched on overriding the viewElements() of this plugin but we can do much more to further customise things. You are also not required to extend the ImageFormatter. There are plenty of existing plugins you can either extend from or use as an example.

在本文中,我们看到了创建字段格式化程序并扩展Drupal 8中的默认行为是多么容易。我们仅涉及覆盖此插件的viewElements() ,但是我们可以做更多的事情来进一步自定义内容。 您也不需要扩展ImageFormatter 。 您可以扩展很多现有的插件,也可以作为示例使用。

Additionally, you can easily create new field types and widgets as well. It’s a similar process but you’ll need to take some schema information into account, use different annotation classes and write some more code. But the point is you are very flexible in doing so.

此外,您还可以轻松创建新的字段类型和窗口小部件。 这是一个类似的过程,但是您需要考虑一些架构信息,使用不同的注释类并编写更多代码。 但关键是您这样做非常灵活。

翻译自: https://www.sitepoint.com/creating-custom-field-formatters-drupal-8/

最新回复(0)