Change record status: 
Project: 
Introduced in branch: 
8.x
Description: 

Fields are now bound to a specific entity type (they are still shareable between bundles) and the storage controller for that entity type handles the CRUD operation of the whole entity. It is possible to create fields named the same on different entity types, these will be completely separate fields not sharing their settings.

Despite the massive internal changes, a lot of entity handling did not change. $node->body->value still works, entities are saved by $node->save() etc. Only code that handled actual field information separately from entities will need to change.

Field information changes

  • field_info_fields() returns a list keyed by field UUID instead of field names, as field names are no longer unique.
  • FieldInfo::getField(),field_info_field(), field_read_field() require an additional $entity_type param
  • FieldInfo::getFieldMap() / field_info_field_map() returns a list keyed by entity_type, then field name.
  • $field->getBundles() returns a list of entity bundle names (was keyed by entity type previously)

Field storage configuration entity changes

The primary identifier of the field storage configuration entity previously was the field_name. Now there's a name instead but that's not enough -- fields are no longer shareable among entity types and so entity_type is part of the primary identifier:

$field_storage = FieldStorageConfig::create(array('entity_type' => $entity_type, 'name' => $name));

These two keys (and properties on the resulting field storage configuration entities) specify which field we are working with. $field_storage->id() is now "$entity_type.$name" instead of $name.

Field storage backends are gone

Storing everything is the responsibility of the entity storage controller. An abstract Drupal\Core\Entity\FieldableEntityStorageControllerBase is provided which has protected methods for reading / writing field values: loadFieldItems(), saveFieldItems()... Those are wrappers that contain the generic handling of the "field data cache". Actual storage processing is delegated to doLoadFieldItems(), doSaveFieldItems() methods that are up to each actual storage class to provide. These methods are implemented DatabaseStorageController by the same storage logic that was previously in field_sql_storage.module. There is also a Drupal\Core\Entity\FieldableEntityStorageControllerInterface which defines methods to deal with configurable field & bundle CRUD.

Also, all of the field storage hooks were removed:
hook_field_storage_create_field
hook_field_storage_delete
hook_field_storage_delete_field
hook_field_storage_delete_instance
hook_field_storage_delete_revision
hook_field_storage_details
hook_field_storage_details_alter
hook_field_storage_info
hook_field_storage_info_alter
hook_field_storage_load
hook_field_storage_pre_insert
hook_field_storage_pre_load
hook_field_storage_pre_update
hook_field_storage_purge
hook_field_storage_purge_field
hook_field_storage_purge_field_instance
hook_field_storage_query
hook_field_storage_update_field
hook_field_storage_write
hook_field_attach_purge

Most of field.attach.inc is gone

The field_attach_load, field_attach_insert, field_attach_update, field_attach_presave, field_attach_delete, field_attach_delete_revision functions are gone without replacement. Associated hooks hook_field_attach_load, hook_field_attach_insert, hook_field_attach_update, hook_field_attach_presave, hook_field_attach_delete, hook_field_attach_delete_revision are gone as well.

Comments

deryck.henson’s picture

Should have always been this way. Just cloned the repo thanks.

RunePhilosof’s picture

The example's use of entity_create is missing the required type key.

loopduplicate’s picture

Here's an example taken from core/modules/editor/src/Tests/EditorLoadingTest.php:83 which creates a formatted text field, which uses an <input type="text">.

    FieldStorageConfig::create(array(
      'field_name' => 'field_text',
      'entity_type' => 'node',
      'type' => 'text',
    ))->save();

chriscalip’s picture

We're stuck with entity_load or node_load which is slow and/or memory intensive. For long running backend scripts the removal of DX utility field_attach_load is an unproductive mess. BRING BACK field_attach_load and field_attach_save
Reference:
https://www.drupal.org/node/2841179
http://drupal.stackexchange.com/questions/199268/how-load-only-some-node...

nitin.k’s picture

Reuse fields example:



use Drupal\Core\Entity\Entity;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\Core\Entity\Entity\EntityFormDisplay;

FieldConfig::create(
array(
  'field_name' => 'field_question1',
  'entity_type' => 'node',
  'label' => 'Question1',
  'bundle' => 'test_content_type_5',
  'type' => 'options_select',
  'settings' => array(
    'handler_settings' => array(
      'target_bundles' => array(
        'yes_no' => 'yes_no'
      )
    )
  ),
  'default_value' => array('target_id' => '3'),
)
)->save();

EntityFormDisplay::load('node.test_content_type_5.default')
->setComponent('field_question1', ['type' => 'options_select'])
->save();

Change in fields value after creation..


$entity_type = 'node';
$bundle = 'test_ct';
$field_name = 'field_question1';
$bundle_fields = \Drupal::getContainer()->get('entity_field.manager')->getFieldDefinitions($entity_type, $bundle);
$field_definition = $bundle_fields[$field_name];
if (is_object($field_definition)) {
  $field_definition->setDefaultValue(---- some value ---);
  $field_definition->save();
}