Define and use a compound¶
This example creates a fresh compound definition. Run it once in a bootstrapped Drupal development environment, after enabling Compound Field.
use Drupal\compound_field\Entity\CompoundField;
$compound = CompoundField::create([
'id' => 'speaker',
'label' => 'Speaker card',
'fields' => [
'name' => [
'field_type' => 'string',
'label' => 'Name',
],
'topic' => [
'field_type' => 'string',
'label' => 'Topics',
'cardinality' => 3,
],
],
]);
$compound->save();
Attach compound_field:speaker through normal FieldStorageConfig and
FieldConfig, or through Field UI. The host storage's
cardinality can be FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED.
That does not change the sub-field caps.
Read, validate and save¶
With a loaded Conference node and its field_speakers field:
$node->set('field_speakers', [
[
'name' => 'Ada Lovelace',
'topic' => [
['value' => 'Computing history'],
['value' => 'Analytical engines'],
],
],
]);
$violations = $node->validate();
if ($violations->count() !== 0) {
throw new \RuntimeException('Conference values failed validation.');
}
$node->save();
$name = $node->get('field_speakers')->first()->get('name')->get('value')->getValue();
The normal entity API does not automatically validate every programmatic save. Handle violations before persisting user-supplied values. Do not expose detailed internal exceptions to an untrusted client.
storage_settings belongs to a sub-field's storage definition, such as a string's
maximum length or a reference's target entity type. settings contains field
settings, such as a reference handler and allowed bundles. Their defaults come
from the field type.
For an existing, in-use compound, change its declared fields through the
deployment guide. Read
getDeclaredFields() before writing setFields() when the compound uses composition;
getFields() also contains included fields.
Storage settings¶
Compound storage_settings use the field type's exported configuration shape.
For Options fields, write allowed_values as
[['value' => 'red', 'label' => 'Red']]. A standalone FieldStorageConfig instead
takes the runtime map ['red' => 'Red']; mixing these shapes can cause schema
errors. Compound Field converts sub-field settings for the plugin at runtime.
Changing datetime_type on an in-use sub-field is refused even when its column
specification is unchanged, because it changes how stored values are interpreted.
Retiring populated allowed-value keys needs explicit consent.
Include another compound's fields¶
Given a person compound, this export adds its sub-fields directly to employee:
id: employee
label: Employee
includes:
- person
fields:
cv:
field_type: file
label: CV
Use the compound's Composition tab or set includes in configuration.
getDeclaredFields() returns only local definitions; getFields() resolves
included fields first, transitively, then local fields. Repeated bases
contribute once. Duplicate sub-field names, missing bases and cycles are refused.
An inclusion adds no value nesting. A sub-field of type compound_field:person
instead holds a nested person record. Both count toward the expanded column
budget. Edit inherited fields on their declaring compound; changes affect every
dependent host storage. An in-use dependent prevents deleting its base.
Deleting an unused base can cascade to unused dependents.
Change an in-use definition¶
Use the structural pipeline instead of saving the definition directly:
$fields = $compound->getDeclaredFields();
$fields['phone'] = ['field_type' => 'telephone', 'label' => 'Phone'];
unset($fields['fax']);
$compound->setFields($fields);
$request = \Drupal\compound_field\StructuralChange\CompoundFieldStructuralChangeRequest::create()
->acknowledgeRemoval('fax');
$pipeline = \Drupal::service('compound_field.structural_change_pipeline');
$plan = $pipeline->plan($compound, NULL, $request);
// Inspect $plan->describe() before applying.
$pipeline->apply($compound, $request);
Changes to includes use this pipeline too. Removing an inclusion requires
acknowledging the sub-fields it removes. See the
deployment guide for imports and recovery.