Khanh Hoang - Kenn
Kenn is a user experience designer and front end developer who enjoys creating beautiful and usable web and mobile experiences.
>>Drupal 8: Creating a custom field - Part 2: Field widget
I have been experimenting with the Alpha release of Drupal 8 and so I'm sharing some of my experiences so that you can avoid the pitfalls I have encountered.
First I would like to give credit to the two articles I used during the exercise:
Hopefully this article will provide a third point-of-view to make your task easier.
In D8 the location of files is very important. The field type must be located as follows:
<module_name>/lib/Drupal/<module_name>/Plugin/field/field_type/<field_type_name>.php
N.B. The field type name should be in CamelCase.
In the newly created field type file add a brief comment to explain what it consists of:
/** * @file * Contains \Drupal\<module_name>\Plugin\field\field_type\<field_type_name>. */
N.B. The "Contains..." line should match the location and name of this file.
Then add the namespace as follows:
namespace Drupal\<module_name>\Plugin\field\field_type;
N.B. It is vital that the namespace matches the location of the file otherwise it will not work.
Then add the following uses:
use Drupal\field\Plugin\Type\FieldType\ConfigFieldItemBase;
This provides the class that the field item will extend.
use Drupal\field\FieldInterface;
This provides a variable type required within the field item class.
Annotations are an important part of Drupal 8 and must not be treated as simple comments! :o) The annotation should appear as follows:
/** * Plugin implementation of the '<field_type_name>' field type. * * @FieldType( * id = "<field_type_id>", * label = @Translation("<field_type_label>"), * description = @Translation("<field_type_description>"), * default_widget = "<field_type_default_widget>", * default_formatter = "<field_type_default_formatter>" * ) */
N.B. All text represented by a <placeholder> should be appropriately replaced according to requirements. The default_widget and default_formatter must match the ids of a widget and a formatter (see Part 2 of this article).
Create the field item class as follows:
class <field_type_name> extends ConfigFieldItemBase { }
N.B. The <field_type_name> must match the name of this file (case-sensitive).
The class should contain the following:
The schema() function defines the sub-field(s) that make up the field item. Here is an example:
/** * {@inheritdoc} */ public static function schema(FieldInterface $field) { return array( 'columns' => array( 'forename' => array( 'type' => 'varchar', 'length' => 256, 'not null' => TRUE, ), 'surname' => array( 'type' => 'varchar', 'length' => 256, 'not null' => TRUE, ), 'age' => array( 'type' => 'int', 'not null' => TRUE, ), ), ); }
The isEmpty() function defines what constitutes an empty field item, e.g.
/** * {@inheritdoc} */ public function isEmpty() { $value = $this->get('forename')->getValue(); return $value === NULL || $value === ''; }
The getPropertyDefinitions() function defines the data types of the fields, e.g.
/** * {@inheritdoc} */ static $propertyDefinitions; /** * {@inheritdoc} */ public function getPropertyDefinitions() { if (!isset(static::$propertyDefinitions)) { static::$propertyDefinitions['forename'] = array( 'type' => 'string', 'label' => t('Forename'), ); static::$propertyDefinitions['surname'] = array( 'type' => 'string', 'label' => t('Surname'), ); static::$propertyDefinitions['age'] = array( 'type' => 'integer', 'label' => t('Age'), ); } return static::$propertyDefinitions; }
Here is a simple example, similar to that described above.