Fields are powered through the plugin system in Drupal. Field types are defined using the plugin system. Each field type has its own class. A new field type can be defined through a custom class that will provide schema and property information.
In this example, we will create a simple field type called "real name" to store the first and last names.
Create a new module like the one existing in the first recipe. We will refer to the module as mymodule
throughout the recipe. Use your module's appropriate name.
src/Plugin/Field/FieldType
directory in the module's base location. The Field
module discovers field types in the PluginFieldFieldType
namespace.RealName.php
file in the newly created directory so that we can define the RealName
class. This will provide our real name
field for the first and last names:RealName
class will extend the DrupalCoreFieldFieldItemBase
class:<?php /** * @file * Contains DrupalmymodulePluginFieldFieldTypeRealName. */ namespace DrupalmymodulePluginFieldFieldType; use DrupalCoreFieldFieldItemBase; use DrupalCoreFieldFieldStorageDefinitionInterface; use DrupalCoreTypedDataDataDefinition; class RealName extends FieldItemBase { }
The DrupalCoreFieldFieldItemBase
satisfies methods defined by inherited interfaces except for schema
and propertyDefinitions
.
<?php /** * @file * Contains DrupalmymodulePluginFieldFieldTypeRealName. */ namespace DrupalmymodulePluginFieldFieldType; use DrupalCoreFieldFieldItemBase; use DrupalCoreFieldFieldStorageDefinitionInterface; use DrupalCoreTypedDataDataDefinition; /** * Plugin implementation of the 'realname' field type. * * @FieldType( * id = "realname", * label = @Translation("Real name"), * description = @Translation("This field stores a first and last name."), * category = @Translation("General"), * default_widget = "string_textfield", * default_formatter = "string" * ) */ class RealName extends FieldItemBase { }
The @FieldType
tells Drupal that this is a FieldType
plugin. The following properties are defined:
Id
: This is the plugin's machine nameLabel
: This is the human-readable name for the fielddescription
: This is the human-readable description of the fieldcategory
: This is the category where the field shows up in the user interfacedefault_widget
: This is the default form widget to be used for editingdefault_formatter
: This is the default formatter with which you can display the fieldRealName
class needs to implement the schema
method defined in the DrupalCoreFieldFieldItemInterface
. This returns an array of the database API schema information:/** * {@inheritdoc} */ public static function schema(DrupalCoreFieldFieldStorageDefinitionInterface $field_definition) { return array( 'columns' => array( 'first_name' => array( 'description' => 'First name.', 'type' => 'varchar', 'length' => '255', 'not null' => TRUE, 'default' => '', ), 'last_name' => array( 'description' => 'Last name.', 'type' => 'varchar', 'length' => '255', 'not null' => TRUE, 'default' => '', ), ), 'indexes' => array( 'first_name' => array('first_name'), 'last_name' => array('last_name'), ), ); }
The schema
method defines the columns in the field's data table. We will define a column to hold the first_name
and last_name
values.
propertySchema
method to satisfy DrupalCoreTypedDataComplexDataDefinitionInterface
. This returns a typed definition of the values defined in the schema
method:/** * {@inheritdoc} */ public static function propertyDefinitions(DrupalCoreFieldFieldStorageDefinitionInterface $field_definition) { $properties['first_name'] = DrupalCoreTypedDataDataDefinition::create('string') ->setLabel(t('First name')); $properties['last_name'] = DrupalCoreTypedDataDataDefinition::create('string') ->setLabel(t('Last name')); return $properties; }
This method returns an array that is keyed with the same column names provided in schema
. It returns a typed data definition to handle the field type's values.
Drupal core defines a plugin.manager.field.field_type
service. By default, this is handled through the DrupalCoreFieldFieldTypePluginManager
class. This plugin manager defines the field type plugins that should be in the Plugin/Field/FieldType
namespace, and all the classes in this namespace will be loaded and assumed to be field type plugins.
The manager's definition also sets DrupalCoreFieldFieldItemInterface
as the expected interface that all the field type plugins will implement. This is why most field types extend DrupalCoreFieldFieldItemBase
to meet these method requirements.
As field types are annotated plugins, the manager provides DrupalCoreFieldAnnotationFieldType
as the class that fulfills the annotation definition.
When the user interface defines the available fields, the plugin.manager.field.field_type
service is invoked to retrieve a list of available field types.
The DrupalCoreFieldFieldTypePluginManager
class defines the alter
method as field_info.
Modules that implement hook_field_info_alter
in their .module
files have the ability to modify field type definitions discovered by the manager:
/** * Implements hook_field_info_alter(). */ function mymodule_field_info_alter(&$info) { $info['email']['label'] = t('E-mail address'); }
The preceding alter
method will change the human-readable label for the Email
field to the e-mail address.
The DrupalCoreTypedDateComplexDataInterface
interface provides an isEmpty
method. This method is used to check whether the field's value is empty, for example, when verifying that the required field has data. The DrupalCoreTypedDataPluginDataTypeMap
class implements the method. By default, the method ensures that the values are not empty.
Field types can provide their own implementations to provide a more robust verification. For instance, the field can validate that the first name can be entered but not the last name, or the field can require both the first and the last name.