Create a custom field type
Field types define the properties and behaviors of fields. Field types are defined as plugins, so it's a good idea to familiarize yourself with the Plugin API before diving into writing a new field type.
To create a field type in Drupal you need a class with the FieldType PHP attribute.
The location of the field type class should be placed inside MODULE_NAME/src/Plugin/Field/FieldType
/modules/foo/src/Plugin/Field/FieldType/BazItem.php
The namespace of that class should be Drupal\MODULE_NAME\Plugin\Field\FieldType
<?php
namespace Drupal\MODULE_NAME\Plugin\Field\FieldType;
The PHP attribute above the class should include a unique id, a label, and the default formatter. The default formatter will be the ID used in the PHP attribute of the field formatter class.
use Drupal\Core\Field\Attribute\FieldType;
use Drupal\Core\StringTranslation\TranslatableMarkup;
/**
* Provides a field type of baz.
*/
#[FieldType(
id: "baz",
label: new TranslatableMarkup("Baz field"),
description: new TranslatableMarkup("Field to store Baz values."),
default_widget: "baz_widget",
default_formatter: "baz_formatter",
)]The class needs to implement the FieldItemInterface interface. And should extend the FieldItemBase class for common implementation of the interface.
class BazItem extends FieldItemBase {
}
FieldItemInterface::schema() should be overridden, in order to tell the system how to store the value(s) for the field
/**
* {@inheritdoc}
*/
public static function schema(FieldStorageDefinitionInterface $field_definition) {
return [
// columns contains the values that the field will store
'columns' => [
// List the values that the field will save. This
// field will only save a single value, 'value'
'value' => [
'type' => 'text',
'size' => 'tiny',
'not null' => FALSE,
],
],
];
}
This method returns an array of Schema API column specifications.
The method FieldItemInterface::propertyDefinitions() tells the system more details about your properties and/or validation constraints of the field. See the IDs in the plugin PHP attribute of the DataTypes defined in the core/lib/Drupal/Core/TypedData/Plugin/DataType directory. Core constraints are defined in the core/lib/Drupal/Core/Validation/Plugin/Validation/Constraint directory.
/**
* {@inheritdoc}
*/
public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
$properties = [];
$properties['value'] = DataDefinition::create('string')
->setLabel(t('Value'))
->setRequired(TRUE);
return $properties;
}The method Map::isEmpty (an ancestor of FieldItemBase) should be overridden, telling the system how to determine when the field is empty.
/**
* {@inheritdoc}
*/
public function isEmpty() {
$value = $this->get('value')->getValue();
return $value === NULL || $value === '';
}Field Settings
Field settings allow users to customize the field according to their needs. If the field has any field settings, three steps need to be taken:
- Override FieldItemBase::defaultFieldSettings() in order to set the defaults
- Create the configuration schema for the settings you've created
- Create a form to allow users to change the settings
Step 1: Override FieldItemBase::defaultFieldSettings()
/**
* {@inheritdoc}
*/
public static function defaultFieldSettings() {
return [
// Declare a single setting, 'size', with a default
// value of 'large'
'size' => 'large',
] + parent::defaultFieldSettings();
}
Step 2: Create the configuration schema for the settings you've created
Configuration schema goes in the following file:
[MODULE ROOT]/config/schema/[MODULE_NAME].schema.ymlIn this file, you will describe the data type(s) of the setting(s) you've created in defaultFieldSettings():
Step 1 created a setting named 'size', that stores a string value. The schema for this would look like the following:
field.field_settings.[FIELD ID]:
type: mapping
label: 'FIELDNAME settings'
mapping:
size:
type: string
label: 'Size'
Step 3: Create a form to allow users to change the settings
Add namespace FormStateInterface to FieldType file:
use Drupal\Core\Form\FormStateInterface;The form to allow for users to change the values for the settings is created by overriding FieldItemBase::fieldSettingsForm()
/**
* {@inheritdoc}
*/
public function fieldSettingsForm(array $form, FormStateInterface $form_state) {
$element = [];
// The key of the element should be the setting name
$element['size'] = [
'#title' => $this->t('Size'),
'#type' => 'select',
'#options' => [
'small' => $this->t('Small'),
'medium' => $this->t('Medium'),
'large' => $this->t('Large'),
],
'#default_value' => $this->getSetting('size'),
];
return $element;
}
Real Example
The RgbItem from the field_example module under the examples project:
<?php
namespace Drupal\field_example\Plugin\Field\FieldType;
use Drupal\Core\Field\Attribute\FieldType;
use Drupal\Core\Field\FieldItemBase;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\Core\TypedData\DataDefinition;
/**
* Plugin implementation of the 'field_example_rgb' field type.
*/
#[FieldType(
id: "field_example_rgb",
label: new TranslatableMarkup("Example Color RGB"),
description: new TranslatableMarkup("Demonstrates a field composed of an RGB color."),
default_widget: "field_example_text",
default_formatter: "field_example_simple_text",
)]
class RgbItem extends FieldItemBase {
/**
* {@inheritdoc}
*/
public static function schema(FieldStorageDefinitionInterface $field_definition) {
return [
'columns' => [
'value' => [
'type' => 'text',
'size' => 'tiny',
'not null' => FALSE,
],
],
];
}
/**
* {@inheritdoc}
*/
public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
$properties['value'] = DataDefinition::create('string')->setLabel(t('Hex value'));
return $properties;
}
/**
* {@inheritdoc}
*/
public function isEmpty() {
$value = $this->get('value')->getValue();
return $value === NULL || $value === '';
}
}
Help improve this page
You can:
- Log in, click Edit, and edit this page
- Log in, click Discuss, update the Page status value, and suggest an improvement
- Log in and create a Documentation issue with your suggestion
Still on Drupal 7? Security support for Drupal 7 ended on 5 January 2025. Please visit our Drupal 7 End of Life resources page to review all of your options.