EntityReferenceItem is more complicated than just the "entity" DataReferenceDefinition.
It has a DataReferenceDefinition for "target_id" as well.
I solved a similar issue by extending EntityReferenceItem.
Then you can get the entity from the parent definition, which is a bit long and complex and then just add your custom fields on top:
/**
* {@inheritdoc}
*/
public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
$properties = parent::propertyDefinitions($field_definition);
$properties['street'] = DataDefinition::create('string')
->setLabel(new TranslatableMarkup('Title'));
$properties['city'] = DataDefinition::create('string')
->setLabel(new TranslatableMarkup('Title'));
return $properties;
}
Here's the code I used to add one text field to an EntityReferenceItem:
namespace Drupal\mymodule\Plugin\Field\FieldType;
use Drupal\Core\TypedData\DataDefinition;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemBase;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\Core\Validation\Plugin\Validation\Constraint\AllowedValuesConstraint;
use Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem;
use Drupal\Component\Utility\Random;
/**
* Defines the 'entity_reference' entity field type.
*
* Supported settings (below the definition's 'settings' key) are:
* - target_type: The entity type to reference. Required.
*
* @FieldType(
* id = "entity_reference_with_title",
* label = @Translation("Entity reference with title"),
* description = @Translation("An entity field containing an entity reference and a text field."),
* category = @Translation("Custom"),
* default_widget = "entity_reference_with_title_autocomplete",
* default_formatter = "entity_reference_with_title_entity_view",
* list_class = "\Drupal\Core\Field\EntityReferenceFieldItemList",
* )
*/
class EntityReferenceWithTitle extends EntityReferenceItem {
/**
* {@inheritdoc}
*/
public static function defaultStorageSettings() {
return array(
'target_type' => \Drupal::moduleHandler()->moduleExists('node') ? 'node' : 'user',
'title' => '',
) + parent::defaultStorageSettings();
}
/**
* {@inheritdoc}
*/
public static function defaultFieldSettings() {
return array(
'handler' => 'default',
'handler_settings' => array(),
) + parent::defaultFieldSettings();
}
/**
* {@inheritdoc}
*/
public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
$properties = parent::propertyDefinitions($field_definition);
$properties['title'] = DataDefinition::create('string')
->setLabel(new TranslatableMarkup('Title'));
return $properties;
}
/**
* {@inheritdoc}
*/
public static function mainPropertyName() {
return 'target_id';
}
/**
* {@inheritdoc}
*/
public static function schema(FieldStorageDefinitionInterface $field_definition) {
$schema = parent::schema($field_definition);
$schema['columns'] = array(
'title' => array(
'type' => 'varchar',
'length' => 255,
),
'target_id' => $schema['columns']['target_id'],
);
return $schema;
}
/**
* {@inheritdoc}
*/
public function getConstraints() {
$constraints = FieldItemBase::getConstraints();
// Remove the 'AllowedValuesConstraint' validation constraint because entity
// reference fields already use the 'ValidReference' constraint.
foreach ($constraints as $key => $constraint) {
if ($constraint instanceof AllowedValuesConstraint) {
unset($constraints[$key]);
}
}
return $constraints;
}
/**
* {@inheritdoc}
*/
public static function generateSampleValue(FieldDefinitionInterface $field_definition) {
$manager = \Drupal::service('plugin.manager.entity_reference_selection');
if ($referenceable = $manager->getSelectionHandler($field_definition)->getReferenceableEntities()) {
$random = new Random();
$group = array_rand($referenceable);
$values['target_id'] = array_rand($referenceable[$group]);
$values['title'] = $random->sentences(2);
return $values;
}
}
}