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

  • 3,908