drupal变量术语字段_Drupal 8中的自定义显示套件字段

drupal变量术语字段

Without question, Display Suite is one of the most popular modules in Drupal’s contributed modules history. It allows the creation of layouts, fields and exposes all sorts of other powerful tools we use to build the presentation layer of our Drupal sites.

毫无疑问, Display Suite是Drupal贡献模块历史上最受欢迎的模块之一。 它允许创建布局,字段并公开我们用于构建Drupal网站表示层的各种其他强大工具。

Drupal 8 logo

One of the more powerful features of Display Suite (DS) is the ability to create custom fields that can be displayed inside DS layouts alongside the actual core field values. In Drupal 7, this has been a very popular way of building layouts and showing dynamic data that is not strictly related to the output of any Field API field on the node (or other) entity.

Display Suite(DS)的一项更强大的功能是能够创建自定义字段,该字段可以与实际核心字段值一起显示在DS布局中。 在Drupal 7中,这是一种非常流行的构建布局和显示动态数据的方式,该动态数据与节点(或其他)实体上任何Field API字段的输出均不严格相关。

Display Suite has been ported and is being maintained for Drupal 8. Depending on another contributed module called Layout Plugin, the D8 version offers much of what we have available in Drupal 7 and probably even more.

Display Suite已为Drupal 8移植并维护。取决于另一个名为Layout Plugin的模块,D8版本提供了我们在Drupal 7中可用的很多功能,甚至可能更多。

In this article, we are going to look at how we can create our own Display Suite field in Drupal 8 using the new OOP architecture and plugin system. To demonstrate this, we are going to create a DS field available only on the Article nodes that can be used to display a list of taxonomy terms from a certain vocabulary. And we’re going to make it so that the latter can be configured from the UI, namely admins will be able to specify which vocabulary’s terms should be listed. Not much usefulness in this example, I know, but it will allow you to understand how things work.

在本文中,我们将研究如何使用新的OOP体系结构和插件系统在Drupal 8中创建自己的Display Suite字段。 为了证明这一点,我们将创建一个仅在Article节点上可用的DS字段,该DS字段可用于显示某个词汇表中的分类术语列表。 并且我们将使其能够从UI进行配置,即管理员将能够指定应列出哪些词汇的术语。 我知道在此示例中没有多少用处,但是它将使您了解事物的工作方式。

If you are following along, the code we write is available in this repository inside the Demo module. So feel free to check that out.

如果您一直遵循,我们编写的代码可在此存储库中Demo模块中找到。 因此,随时检查一下。

Drupal 8插件 (Drupal 8 plugins)

Much of the functionality that used to be declared using an _info hook in Drupal 7 is now declared using plugins in Drupal 8. For more information on using plugins and creating your own plugin types, make sure you check out a previous Sitepoint article that talks about just that.

现在,在Drupal 8中使用插件声明了_info_info钩子中声明过的功能。有关使用插件和创建自己的插件类型的更多信息,请确保查看先前有关Sitepoint的文章 ,其中涉及只是。

Display Suite also uses the new plugin system to allow other modules to define DS fields. It exposes a DsField plugin type which allows us to write and maintain all the necessary logic for such a field inside a single plugin class (+ any services we might inject into it). So we no longer implement hook_ds_field_info() and return an array of field information per entity type, but create a plugin class with data straight in its annotation and the relevant logic inside its methods.

Display Suite还使用新的插件系统来允许其他模块定义DS字段。 它公开了一个DsField插件类型,该类型使我们能够在单个插件类(以及我们可能注入其中的任何服务)内编写和维护该字段的所有必要逻辑。 因此,我们不再实现hook_ds_field_info()并返回每个实体类型的字段信息数组,而是创建一个插件类,在其注释中直接包含数据,并在其方法内包含相关逻辑。

VocabularyTerms类 (VocabularyTerms class)

Let us start by creating our plugin class called VocabularyTerms inside the src/plugins/DsField folder of our custom module and annotating it for our purposes:

让我们从在自定义模块的src/plugins/DsField文件夹内创建名为VocabularyTerms的插件类开始,并为我们的目的对其进行注释:

namespace Drupal\demo\Plugin\DsField;

use Drupal\ds\Plugin\DsField\DsFieldBase;

/**
 * Plugin that renders the terms from a chosen taxonomy vocabulary.
 *
 * @DsField(
 *   id = "vocabulary_terms",
 *   title = @Translation("Vocabulary Terms"),
 *   entity_type = "node",
 *   provider = "demo",
 *   ui_limit = {"article|*"}
 * )
 */
class VocabularyTerms extends DsFieldBase {
}

This class alone will hold all of our logic for our very simple DsField plugin. But here are a couple of remarks about what we have so far:

仅此类将包含我们非常简单的DsField插件的所有逻辑。 但是,以下是关于到目前为止我们所拥有的一些评论:

  • The annotation is quite self explanatory: it provides meta information about the plugin.

    注释很容易说明:它提供有关插件的元信息。
  • The class extends DsFieldBase which provides base functionality for all the plugins of this type.

    该类扩展了DsFieldBase ,它为该类型的所有插件提供了基本功能。

  • At the time of writing, the ui_limit annotation has just been committed to HEAD so it might not be available in the release you are using. Limiting the availability of the field on content types and view modes can be done by overriding the isAllowed() method of the base class and performing the logic there.

    在撰写本文时, ui_limit批注刚刚提交给HEAD,因此在您使用的发行版中可能不可用。 可以通过重写基类的isAllowed()方法并在其中执行逻辑来限制字段在内容类型和视图模式上的可用性。

默认配置 (Default configuration)

We want our field to be configurable: the ability to select from a list of existing vocabularies. So let’s start off by providing some defaults to this configuration so that if the user selects nothing, the Tags vocabulary which comes with core will be used. For this, we have to implement the defaultConfiguration() method:

我们希望我们的字段是可配置的:能够从现有词汇表中进行选择。 因此,让我们开始为该配置提供一些默认值,以便如果用户什么都不选择,则将使用core附带的Tags词汇表。 为此,我们必须实现defaultConfiguration()方法:

/**
 * {@inheritdoc}
 */
public function defaultConfiguration() {

  $configuration = array(
    'vocabulary' => 'tags',
  );

  return $configuration;
}

And since we only have one configuration option, we return an array with one element keyed by the configuration name. That’s about it.

由于只有一个配置选项,因此我们返回一个数组,其中包含一个由配置名称作为键的元素。 就是这样

格式化程序 (Formatters)

We also want to have the ability to specify from the UI if the list of taxonomy terms is a series of links to their term pages or formatter as plain text. We could implement this within the configuration realm but let’s do so using formatters instead. And it’s very simple: we implement the formatters() method and return an array of available formatters:

我们还希望能够从UI中指定分类术语列表是否是指向其术语页面或格式器(以纯文本格式)的一系列链接。 我们可以在配置领域中实现此功能,但我们可以使用格式化程序来实现。 这非常简单:我们实现formatters()方法并返回可用的格式化程序数组:

/**
 * {@inheritdoc}
 */
public function formatters() {
  return array('linked' => 'Linked', 'unlinked' => 'Unlinked');
}
DS Field Formatter Options

These will be available for selection in the UI under the Field heading of the Manage Display page of the content type. And we’ll be able to see the choice when we are building the actual field for display. But more on that in a second.

在内容类型的“管理显示”页面的“ Field标题下的UI中可以选择这些选项。 并且,当我们构建实际的显示字段时,我们将能够看到选择。 但更多的是在第二秒。

配置摘要 (Configuration summary)

It’s also recommended that if we are using UI defined settings, we have a summary of what has been selected as a simple string that describes it. This gets printed under the Widget heading of the Manage Display page of the content type.

如果我们使用的是UI定义的设置,还建议您对被选择为描述它的简单字符串的摘要进行总结。 它将打印在内容类型的“管理显示”页面的“ Widget标题下。

DS Configuration Summary

To do this, we need to implement the settingsSummary() method and return said text:

为此,我们需要实现settingsSummary()方法并返回所述文本:

/**
 * {@inheritdoc}
 */
public function settingsSummary($settings) {
  $config = $this->getConfiguration();
  $no_selection = array('No vocabulary selected.');

  if (isset($config['vocabulary']) && $config['vocabulary']) {
    $vocabulary = Vocabulary::load($config['vocabulary']);
    return $vocabulary ? array('Vocabulary: ' . $vocabulary->label()) : $no_selection;
  }

  return $no_selection;
}

Here we start getting more intimate with the actual configuration that was stored with the field, available by calling the getConfiguration() method on our plugin class. What we do above, then, is check if the vocabulary setting has been set, we load it based on its machine name using the Vocabulary class and return an array of strings that need to be printed.

在这里,我们开始更加了解与字段存储的实际配置,可以通过在插件类上调用getConfiguration()方法获得该配置。 然后,我们上面的操作是检查是否设置了词汇表设置,我们使用Vocabulary类根据其机器名称加载它,并返回需要打印的字符串数组。

Since we are referencing the Vocabulary class, we also need to use it at the top:

由于我们引用的是Vocabulary类,因此我们还需要在顶部使用它:

use Drupal\taxonomy\Entity\Vocabulary;

Important to note: I am using Vocabulary statically here to load an entity for the sake of brevity. It is highly recommended you inject the relevant storage using dependency injection and use that to load entities. The same goes for most classes you’ll see me referencing statically below.

需要注意的重要事项 :为了简洁起见,我在此处静态使用Vocabulary加载实体。 强烈建议您使用依赖项注入来注入相关存储,并使用它来加载实体。 大多数类也是如此,您将在下面看到我静态引用的内容。

设定表格 (Settings form)

Now that we display which configuration has been chosen from the UI, it’s time to provide the actual form which will allow the user to do so. This will be made available by clicking the cogwheel under the Operations heading of the Manage Display page of the content type.

现在,我们显示了从UI中选择了哪种配置,是时候提供允许用户进行操作的实际表格了。 单击内容类型的“管理显示”页面的“ Operations标题下的齿轮,将使其可用。

DS Field Settings Form
/**
 * {@inheritdoc}
 */
public function settingsForm($form, FormStateInterface $form_state) {
  $config = $this->getConfiguration();

  $names = taxonomy_vocabulary_get_names();
  $vocabularies = Vocabulary::loadMultiple($names); 
  $options = array();
  foreach ($vocabularies as $vocabulary) {
    $options[$vocabulary->id()] = $vocabulary->label();
  }
  $settings['vocabulary'] = array(
    '#type' => 'select',
    '#title' => t('Vocabulary'),
    '#default_value' => $config['vocabulary'],
    '#options' => $options,
  );

  return $settings;
}

Like before, we need to implement a method for this. And what we do inside is load all the taxonomy vocabulary names and prepare an array of options to be used with a Form API select list. The latter is the only element we need for this form.

像以前一样,我们需要为此实现一个方法。 我们要做的是加载所有分类法词汇名称并准备要与Form API选择列表一起使用的选项数组。 后者是我们需要此表单的唯一元素。

渲染领域 (Rendering the field)

The last thing left to do is implement the build() method responsible for rendering the contents of our field:

剩下要做的最后一件事是实现build()方法,该方法负责呈现我们字段的内容:

/**
 * {@inheritdoc}
 */
public function build() {
  $config = $this->getConfiguration();
  if (!isset($config['vocabulary']) || !$config['vocabulary']) {
    return;
  }

  $query = \Drupal::entityQuery('taxonomy_term')
    ->condition('vid', $config['vocabulary']);

  $tids = $query->execute();
  if (!$tids) {
    return;
  }

  $terms = Term::loadMultiple($tids);
  if (!$terms) {
    return;
   }

  return array(
    '#theme' => 'item_list',
    '#items' => $this->buildTermList($terms),
  );
}

So what do we do here? First, we access the chosen vocabulary from the configuration. Then we run an EntityQuery to find all the terms in this vocabulary. Next, we load all these terms and finally we return a render array that uses the item_list theme to print our terms.

那么我们在这里做什么? 首先,我们从配置中访问所选词汇。 然后,我们运行EntityQuery来查找此词汇表中的所有术语。 接下来,我们加载所有这些术语,最后返回一个使用item_list主题打印术语的渲染数组。

Although we don’t need it here, in most cases you’ll need to access the node entity that is currently being rendered. That is available inside the configuration array under the entity key. Moreover, under the build key you have the actual render array of the node being built. So keep this in mind and do inspect the other elements of the configuration array on your own for more information.

尽管这里我们不需要它,但是在大多数情况下,您需要访问当前正在渲染的节点实体。 在entity键下的配置数组中可用。 此外,在build键下,您具有要构建的节点的实际渲染数组。 因此,请记住这一点,并自行检查配置阵列的其他元素以获取更多信息。

I would like to mention a few more things before we take a look at the actual buildTermList() method. First, for brevity, we used the EntityQuery service statically. In your project, you should inject it. Second, we used the Term class statically to load the taxonomy term entities. Again, you should inject its storage and use that for this purpose. And lastly, we should import the Term class at the top with use:

在我们看一下实际的buildTermList()方法之前,我想说几件事。 首先,为简便起见,我们静态使用EntityQuery服务。 在您的项目中,应该注入它。 其次,我们静态地使用Term类来加载分类术语实体。 同样,您应该注入它的存储并将其用于此目的。 最后,我们应该use在顶部导入Term类:

use Drupal\taxonomy\Entity\Term;

Now that this is clear, let’s take a look at our own buildTermList() method:

现在已经很清楚了,让我们看一下我们自己的buildTermList()方法:

private function buildTermList(array $terms) {
  $config = $this->getConfiguration();
  $formatter = isset($config['field']['formatter']) && $config['field']['formatter'] ? $config['field']['formatter'] : 'unlinked';
  $items = array();
  foreach ($terms as $term) {
    $items[] = $this->buildTermListItem($term, $formatter);
  }

  return $items;
}

This method is responsible for getting the field formatter, looping through the term entities and building an array of term information that can be printed using the item_list theme. As you can see, though, the individual term entity and formatter are passed to yet another helper method to keep things nice and tidy:

此方法负责获取字段格式化程序,遍历术语实体并构建可以使用item_list主题打印的术语信息数组。 但是,如您所见,各个术语实体和格式化程序被传递给另一个帮助器方法,以使事情保持整洁:

private function buildTermListItem(Term $term, $formatter) {
  if ($formatter === 'linked') {
    $link_url = Url::fromRoute('entity.taxonomy_term.canonical', array('taxonomy_term' => $term->id()));
    return \Drupal::l($term->label(), $link_url);
  }

  return SafeMarkup::checkPlain($term->label());
}

Finally, in the buildTermListItem() method we either return the sanitized title of the term or a link to it depending on the formatter.

最后,在buildTermListItem()方法中,我们要么返回术语的清理过的标题,要么根据格式化程序返回到它的链接。

Again we see classes which should be injected but were used statically to save some space. With the risk of sounding like a broken record, keep in mind that you should inject these. For now, we must use them at the top:

再次,我们看到了应该注入但静态使用的类,以节省一些空间。 听起来好像有破损记录的风险,请记住应该注入这些。 现在,我们必须在顶部使用它们:

use Drupal\Core\Url;
use Drupal\Component\Utility\SafeMarkup;

结论 (Conclusion)

And there we have it, our very own DsField plugin in Drupal 8. Clearing the caches would now make this field available on all view modes of the Article content type.

现在,有了它,Drupal 8中我们自己的DsField插件。清除缓存将使该字段在Article内容类型的所有视图模式下都可用。

alt

Moreover, it can be configured to choose among multiple vocabularies, the terms of which it will then display. And finally, we can even specify a formatter to print these terms either linked or as plain text.

此外,它可以配置为在多个词汇中进行选择,然后显示词汇。 最后,我们甚至可以指定一个格式程序来打印这些链接或纯文本形式的术语。

翻译自: https://www.sitepoint.com/custom-display-suite-fields-in-drupal-8/

drupal变量术语字段

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值