Drupal 8 Field API
Easier then ever!
Dmitry Olaresko
skype: d.olaresko
email: dolaresko@adyax.com
The Core
-
PSR-4
-
Everything is an Entity
-
Fieldable Blocks
-
In-Place Editor
-
Core fields:
-
Entity Reference!
-
Date
-
Link
-
Email
-
Phone (<input type="tel">)
-
Comment field!
-
-
Form modes
Entity Field API
-
ContentEntity:
Everything is a field
-
Only !two! interfaces
-
-
FieldItemListInterface
-
FieldItemInterface
-
$entity->body; //FieldItemListInterface
$entity->field_example; //FieldItemListInterface
$entity->title; //FieldItemListInterface
$entity->field_example->get(0); //FieldItemInterface
$entity->field_example[0];
$entity->field_example[0]->value; //Field Value
$entity->field_example[0]->getValue();
$entity->field_example->value;
-
Item List:
-
Item:
-
Value:
HINT!
Don`t forget to use
$entity->hasField($field_name);
Pros and Cons
- Translatable
- Revision support
- Iteratable
- Interact with parent objects
foreach ($entity->field_products as $delta => $product) {
...
}
$item->getEntity();
$item->getLangcode();
$item->getFieldDefinition();
+
- Extend Item and ItemList per field type
- Computed fields
$term = $entity->term->entity; //TaxonomyTerm object
+
+
+
+
+
$entity->tags->getRefencedEntities(); //EntityReferenceItemList
$term_field = $entity->term->entity->field_image;
- Impossible to use single field for different entity types
-
Kinds of fields
-
Base fields
-
Configurable fields
-
Custom
(properties)
(UI, YAML)
(oldSchool modules)
Base Fields
Define
public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
$fields['title'] = BaseFieldDefinition::create('string')
->setLabel(t('Title'))
->setDescription(t('The title of this node.'))
->setRequired(TRUE)
->setTranslatable(TRUE)
->setRevisionable(TRUE)
->setDefaultValue('')
->setSetting('max_length', 255)
->setDisplayOptions('view', array(
'label' => 'hidden',
'type' => 'string',
'weight' => -5,
))
->setDisplayOptions('form', array(
'type' => 'string_textfield',
'weight' => -5,
))
->setDisplayConfigurable('form', TRUE);
// Other base field definitions.
return $fields;
}
hook_entity_base_field_info()
hook_entity_base_field_info_alter()
function hook_entity_base_field_info(\Drupal\Core\Entity\EntityTypeInterface $entity_type) {
if ($entity_type->id() == 'node') {
$fields = array();
$fields['example_text'] = BaseFieldDefinition::create('string')
->setLabel(t('Example text'))
->setDescription(t('Field description.'))
->setComputed(TRUE)
->setClass('\Drupal\example_module\EntityComputedText');
return $fields;
}
}
function hook_entity_base_field_info_alter(&$fields,
\Drupal\Core\Entity\EntityTypeInterface $entity_type) {
// Alter the example_text field to use a custom class.
if ($entity_type->id() == 'node' && !empty($fields['example_text'])) {
$fields['example_text']->setClass('\Drupal\example_module\EntityComputedText');
}
}
Definitions
Field (base)
Field Instance
Field storage
Field
+
+
D7
D8
FieldStorageDefinitionInterface
FieldDefinitionInterface
FieldStorageConfig
Entity type: field_storage_config
field.storage.<entity_type>.field_name>.yml
uuid: 8996a594-1a01-45b8-af30-485052839880
langcode: en
status: true
dependencies:
module:
- node
- text
id: node.body
field_name: body
entity_type: node
type: text_with_summary
settings: { }
module: text
locked: false
cardinality: 1
translatable: true
indexes: { }
OR
$field_storage = FieldStorageConfig::create(array(
'entity_type' => 'entity_test',
'field_name' => 'field_test',
'type' => 'entity_reference',
'settings' => array(
'target_type' => 'entity_test',
),
'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED,
));
$field_storage->save();
$field_storage = entity_create('field_storage_config', array(
'field_name' => 'body',
'entity_type' => 'block_content',
'type' => 'text_with_summary',
));
$field_storage->save();
FieldConfig
Entity type: field_config
$field = FieldConfig::create(array(
'field_storage' => $field_storage,
'bundle' => 'entity_test',
'label' => t('Test field'),
));
$field->save();
$field = entity_create('field_config', array(
'field_storage' => $field_storage,
'bundle' => 'page',
'label' => t('Body'),
'settings' => array('display_summary' => FALSE),
));
OR
uuid: ae2c5b56-a0e5-44d3-ae00-c289200a608f
langcode: en
status: true
dependencies:
entity:
- field.storage.node.body
- node.type.page
id: node.page.body
field_name: body
entity_type: node
bundle: page
label: Body
description: ''
required: false
translatable: true
default_value: { }
default_value_callback: ''
settings:
display_summary: true
third_party_settings: { }
field_type: text_with_summary
field.field.<entity_type>.<bundle>.<field_name>.yml
$entity->getFieldDefinitions();
$entity->getFieldDefinition($field_name);
$entity_manager = Drupal::entityManager();
$entity_manager->getFieldDefinitions($entity_type_id, $bundle);
$entity_manager->getFieldStorageDefinitions($entity_type_id);
$item->getFieldDefinition();
Get Definitions
Global:
From entity:
From fieldItem:
Plugins
Widgets
Formatters
Field Types
Widget
namespace Drupal\link\Plugin\Field\FieldWidget;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\WidgetBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\link\LinkItemInterface;
/**
* Plugin implementation of the 'link' widget.
*
* @FieldWidget(
* id = "link_default",
* label = @Translation("Link"),
* field_types = {
* "link"
* }
* )
*/
class LinkWidget extends WidgetBase {
// Code here.
}
interface WidgetInterface extends WidgetBaseInterface {
/** Returns a form to configure settings for the widget. */
public function settingsForm(array $form, FormStateInterface $form_state);
/** Returns a form to configure settings for the widget. */
public function settingsSummary();
/** Returns the form for a single field widget. */
public function formElement(FieldItemListInterface $items, $delta,
array $element, array &$form, FormStateInterface $form_state);
/** Assigns a field-level validation error to the right widget sub-element. */
public function errorElement(array $element, ConstraintViolationInterface $violation,
array $form, FormStateInterface $form_state);
/** Massages the form values into the format expected for field values. */
public function massageFormValues(array $values, array $form,
FormStateInterface $form_state);
/** Returns if the widget can be used for the provided field. */
public static function isApplicable(FieldDefinitionInterface $field_definition);
}
Formatters
namespace Drupal\link\Plugin\Field\FieldFormatter;
use Drupal\Component\Utility\String;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\FormatterBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;
use Drupal\link\LinkItemInterface;
use Symfony\Component\HttpFoundation\Request;
/**
* Plugin implementation of the 'link' formatter.
*
* @FieldFormatter(
* id = "link",
* label = @Translation("Link"),
* field_types = {
* "link"
* }
* )
*/
class LinkFormatter extends FormatterBase {
// Code here.
}
interface FormatterInterface extends PluginSettingsInterface {
/** Returns a form to configure settings for the formatter. */
public function settingsForm(array $form, FormStateInterface $form_state);
/** Returns a short summary for the current formatter settings. */
public function settingsSummary();
/** Allows formatters to load information for field values being displayed. */
public function prepareView(array $entities_items);
/** Builds a renderable array for a fully themed field. */
public function view(FieldItemListInterface $items);
/** Builds a renderable array for a field value. */
public function viewElements(FieldItemListInterface $items);
/** Returns if the formatter can be used for the provided field. */
public static function isApplicable(FieldDefinitionInterface $field_definition);
}
Field Type
namespace Drupal\link\Plugin\Field\FieldType;
use Drupal\Component\Utility\Random;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemBase;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\TypedData\DataDefinition;
use Drupal\Core\TypedData\MapDataDefinition;
use Drupal\link\LinkItemInterface;
/**
* Plugin implementation of the 'link' field type.
*
* @FieldType(
* id = "link",
* label = @Translation("Link"),
* description = @Translation("Stores a URL string..."),
* default_widget = "link_default",
* default_formatter = "link",
* constraints = {"LinkType" = {}}
* )
*/
class LinkItem extends FieldItemBase implements LinkItemInterface {
// Code here.
}
interface FieldItemInterface extends ComplexDataInterface {
// Magic methods.
public function __get($property_name);
public function __set($property_name, $value);
public function __isset($property_name);
public function __unset($property_name);
public static function propertyDefinitions(
FieldStorageDefinitionInterface $field_definition);
public static function mainPropertyName();
public static function schema(FieldStorageDefinitionInterface $field_definition);
public function getEntity();
public function getLangcode();
public function getFieldDefinition();
public function view($display_options = array());
public function preSave();
public function insert();
public function update();
public function delete();
public function deleteRevision();
public static function generateSampleValue(FieldDefinitionInterface $field_definition);
public static function defaultStorageSettings();
public static function defaultFieldSettings();
public static function storageSettingsToConfigData(array $settings);
public static function storageSettingsFromConfigData(array $settings);
public static function fieldSettingsToConfigData(array $settings);
public static function fieldSettingsFromConfigData(array $settings);
public function storageSettingsForm(array &$form,
FormStateInterface $form_state, $has_data);
public function fieldSettingsForm(array $form, FormStateInterface $form_state);
}
Useful links
THANK YOU!
Dmitry Olaresko
skype: d.olaresko
email: dolaresko@adyax.com
Field API в Drupal 8
By Dmitry Olaresko
Field API в Drupal 8
- 4,092