Custom Fields

In Chapter 6, Data Modeling and Storage, and Chapter 7, Your Own Custom Entities and Plugin Types, we talked quite extensively about content entities and how they use fields to store the actual data that they are supposed to represent. Then, we saw how these fields, apart from interacting with the storage layer for persisting it, extend TypedData API classes in order to organize this data better at the code level. For example, we saw that the BaseFieldDefinition instances used on entities are actually data definitions (and so are the FieldConfig ones). Moreover, we also saw the Datatype plugins at play there, namely the FieldItemList with their individual items, which down the line extend a basic DataType plugin (Map in most cases). Also, if you remember, when we were talking about these items, I mentioned how they are actually instances of yet another plugin--FieldType. So, essentially, they are a plugin type whose plugins extend plugins of another type. I recommend that you revisit that section if you are fuzzy on the matter.

Most of these concepts are buried inside the Entity API and are only seen and understood by developers. However, the FieldType plugins (together with their corresponding FieldWidget and FieldFormatter plugins) break out and are one of the principle things site builders and content editors actually work with in the UI. They allow users to input structured data and save it to the database. If you recall, I had mentioned them a few times in Chapters 6 and 7, and I promised you a chapter in which we will see how we can create field types that a site builder can then add to an entity type and use for inputting data. Well, this is that chapter, but first, let's do a quick recap on what we know about them.

Field type plugins extend the lower-level TypedData API to create a unique way of not only representing data (within the context of entities), but also storing it to the database (and other stuff as well). They are primarily known as the type of fields site builders can add to an entity type bundle, for example, a plain text field or a select list with multiple options. Nothing can be more common than that in a CMS.

However, they are also used as entity base field types. If you remember our product entity type's name field definition, we actually did use these plugin types:

$fields['name'] = BaseFieldDefinition::create('string')
  ->setLabel(t('Name'))
  ->setDescription(t('The name of the Product.'))
  ->setSettings([
    'max_length' => 255,
    'text_processing' => 0,
  ])
  ->setDefaultValue('')
  ->setDisplayOptions('view', [
    'label' => 'hidden',
    'type' => 'string',
    'weight' => -4,
  ])
  ->setDisplayOptions('form', [
    'type' => 'string_textfield',
    'weight' => -4,
  ])
  ->setDisplayConfigurable('form', TRUE)
  ->setDisplayConfigurable('view', TRUE);

The create() method of the definition class accepts a FieldType plugin ID. Also, the type of the view display option provided a bit below in the code is a FieldFormatter plugin ID, whereas the type of the form display option provided even lower in the code is a FieldWidget plugin ID.

So, although Drupal has its fair share of complexities, when it comes to fields, things are quite consistent. However, in order to figure out the similarities between base fields and configurable ones, we had to dig a little into the code. The former are not as hip as the ones that you can click together in the UI and which everybody knows are FieldType plugins with corresponding widget and formatter plugins.

A crucial lesson from this introduction that I insist you retain--when defining your custom entities, think about the type of fields you need. If there are bundles that need to have different sets of fields, configurable fields are your choice. Otherwise, base fields are perhaps more appropriate. They sit tightly with your Entity type class, appear on all bundles (if that's something you need), and encourage you to explore the Drupal code base and understand the existing field types, widgets, and formatters better (as well as relevant settings they come with).

Also, when you define base fields, think the same way as you would if adding them through the UI--which field type do I want (find a FieldType plugin), how do I want users to interact with it (find a FieldWidget plugin), and how do I want its values to be shown (find a FieldFormatter plugin). Then, inspect the relevant classes to determine the right settings that will go with them.

In this chapter, we will take a look at how we can create our own custom field type with its own default widget and formatter. To provide a bit of continuity, I am going to ask you to think back to the more complex example employed when talking about the TypedData API--the license plate. We will create a field type designed specifically to store license plates in the following format--CODE NUMBER (just as we saw with the example New York plate). Why?

At the moment, there is no field type that can represent this accurately. Of course, we have the simple text field, but that implies having to add both pieces of data that make up a license plate into the same field, stripping them off its meaning. When we were discussing the TypedData API, we saw that one of its core principles is the ability to apply meaning to a piece of data so as to understand that $license_plate (for example) is actually a license plate from which we can ask its code and its number (as well as some general description if we want to). Similar to this (or actually building on top of this), fields are also about storing this data. So, apart from understanding it in code, we also need to persist it in the same way. That is, placing the individual pieces of data in separate meaningful table columns as to also persist that meaning.

An example from Drupal core that does the same thing is the Text (formatted) field. Apart from its string value, this field also stores a format for each value, which is used upon rendering. Without that format, the string value loses its meaning, and Drupal is no longer able to reliably render it in the way it was intended upon creation. So, you can now see that fields take the idea of meaning from TypedData and also apply it to storage as needed. So, in this chapter, you will learn how these three types of plugins work, by creating your own license plate type field. Let's get started.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset