- π©πͺGermany Anybody Porta Westfalica
I totally agree "something" like extra fields, e.g. a field that returns a programmatically derived ("calculated") value, instead of a database value, makes a lot of sense in core and is definitely needed.
Additionally I agree that the current very simple concept of extra fields should be expanded to OOP and using types (e.g. integer, decimal, text, ...) for representation and formatter, while the value is from code and the field itself should be defined in code.
So to sum things up, we need something that at least solves the need for extra / pseudo fields, but there are lots of possibilities to expand and improve the concept.
- π¦πΉAustria fago Vienna
I totally agree "something" like extra fields, e.g. a field that returns a programmatically derived ("calculated") value, instead of a database value, makes a lot of sense in core and is definitely needed.
Sounds like you are taking about computed fields.
- π©πͺGermany Anybody Porta Westfalica
@fago yes, kind of. I think the whole thing I described is around computed / extra / dynamic / pseudo fields. My proposal was a more complete out-of-the-box solution for such dynamically calculated / derived fields in core, without storage.
Guess with computed fields you mean the contrib project β , that also allows storing these values then. I think that part should be left to contrib indeed.TL;DR: I was talking about making such dynamic fields a first-class-citizen in core. hook_entity_extra_field_info() doesn't feel like that in contrast to other Plugin concepts. Maybe it could be summed up with sth. like: Improve Extra Fields in core and use Plugins.
Is that a bit clearer?
- π©πͺGermany mxh Offenburg
@anybody not sure whether you already know, but computed fields exist in core. Here is an excerpt from entity.api.php:
function hook_entity_base_field_info(\Drupal\Core\Entity\EntityTypeInterface $entity_type) { if ($entity_type->id() == 'node') { $fields = []; $fields['my_module_text'] = BaseFieldDefinition::create('string') ->setLabel(t('The text')) ->setDescription(t('A text property added by my_module.')) ->setComputed(TRUE) ->setClass('\Drupal\my_module\EntityComputedText'); return $fields; } }
- leymannx Berlin
I like how "Improve Extra Fields in core and use Plugins" makes it a solvable task.
- π©πͺGermany Anybody Porta Westfalica
@mxh sorry my fault, indeed I now remember I saw that long ago, and think I also used it in a contrib project, but forgot about it. Instead, I used hook_entity_extra_field_info() a lot in such cases.
Now I'm indeed unsure, if the Plugin idea still makes sense. Let's all think about that for a while. Thank you for the reminder and sorry I didn't remember that.
- π©πͺGermany mxh Offenburg
Looking at some practical use cases, I don't think computed fields would be an equivalent replacement for extra fields.
Extra fields, as elaborated already in previous comments long time ago, mostly serve UI-related things. That means in many cases you'd want to have something like a renderable array and/or Twig template involved when displaying the extra field's "value".
On the other hand, computed fields are at the level of field definitions, which could be seen as the "data layer" maybe (it's one layer between database storage and frontend layer). I also think computed fields may be exposed automatically such as JSON API since they are "real" fields. So it may come with some surprising or even unwanted side effects when trying to use computed field instead of extra field.
Looking at proper replacements, I currently think extra fields are some sort of relict from the past but at times still needed. They're almost impossible to be reused. But they may be still relevant if you still use classic "Manage display" without Layout Builder (or maybe in future Experience Builder) and "Manage form display". For example, I often have to define them when rendering further markup sections within an content entity form in-between other fields.
When using Layout Builder, I'd prefer creating blocks instead of extra fields. They can already be implemented as full plugins and reused at other places if needed. Blocks are the most close equivalent that come to my mind right now. I had SDC in my mind as well but these are a bit lower level than block plugins (you could still write a block plugin on top of a SDC if you want though). Once Experience Builder is available, it might also come with yet another concept.
- πΊπΈUnited States mortona2k Seattle
I've been using UI Patterns, which lets you assign entity values to SDC props/slots. That could be used in multiple ways on a site, so having the value attached to an entity instead of calculated in a block would be helpful.
- π¬π§United Kingdom catch
Adding a related issue.
With manage display vs. layout builder vs. XB/canvas, there is already the issue that the 'Submitted by' information isn't controlled by managed display, and it's also not a single field that can have a formatter. So while it's not an 'extra field' (yet) it's an obvious case in core where we need something that's is a composite of two different fields rendered as one unit.
- π©πͺGermany mxh Offenburg
After some more thoughts I guess the concept of an extra field itself is still valid, even when looking at all other concepts we have now. A plugin-based approach as suggested by @anybody, maybe covering methods for optional configuration and rendering could be straightforward.
Splitting the concept up into "view" and "form" plugins might be worth it, this could make implementations get aligned to single responsibility and core may already prepare as much as it can for rendering at the place where it got placed into.
Maybe something like this:
#[ExtraViewField(id: 'my_extra_field', entity_type: 'node')] class MyExtraViewField implements ExtraViewFieldInterface { public function buildConfigurationForm(...); public function viewElement(array &$element, array &$build): void { // $element has #weight already set and is already attached to $build['my_extra_field'] $element += ['#type' => 'details' ...]; } }
#[ExtraFormField(id: 'my_extra_field', entity_type: 'node')] class MyExtraFormField implements ExtraFormFieldInterface { public function buildConfigurationForm(...); public function formElement(array &$element, array &$form, FormStateInterface $form_state): void { // $element has #weight already set and is already attached to $build['my_extra_field'] $element += ['#type' => 'details' ...]; } }
- π©πͺGermany Anybody Porta Westfalica
@mxh nice draft! Maybe we should put that into a separate issue then?
Some additional thoughts on the draft:
1. entity_type(s) parameter:
#[ExtraViewField(id: 'my_extra_field', entity_type: 'node')]
Would it make sense to allow more than one entity type:
#[ExtraViewField(id: 'my_extra_field', entity_types: ['node', 'user'])]
Or even leave out that parameter to have it on all existing entities automatically?
#[ExtraViewField(id: 'my_extra_field')]
2. Optional display parameter:
#[ExtraViewField(id: 'my_extra_field', entity_type: 'node', displays: ['teaser'])]
3. Configure field ui visibility:
Hide the field entirely in the field ui sorting, only make it available programmatically
#[ExtraViewField(id: 'my_extra_field', ..., visible: FALSE]
4. Set "disabled" by default (maybe this should be assumed):
#[ExtraViewField(id: 'my_extra_field', ..., disabled: true]
π Show extra fields (hook_entity_extra_field_info) only in "Default" display mode by default Active
or
#[ExtraViewField(id: 'my_extra_field', ..., region: 'disabled']
So that the field in region "disabled" by default.Just some ideas to discuss, which I had in the past regarding extra fields... Maybe some of them could alternatively better be methods of the interface?
Another option would be to annotate functions, not classes, like OOP hooks do β ...?! Or maybe better not...
When using a class, the benefit might be to combine the form display, view display and eventually some kind of data handling in one class?! - π¬π§United Kingdom catch
Yeah #53 is pretty encouraging and exporting in a new issue sounds good. Moving this one to a plan.
- π©πͺGermany mxh Offenburg
Answering #54:
Yes of course, the attribute constructor arguments may be defined in the ways we see to make most sense, including support of multiple entity types, default visibility settings etc.
Another option would be to annotate functions, not classes, like OOP hooks do...?! Or maybe better not...
OOP hooks make sense to be defined on methods since they address single invokable functions. Extra fields on the other hand may involve more things besides the main rendering / widget logic. One thing that may be often used is building the configuration form. Having all of that resided in one class that belongs to the extra field's functionality would be great. So using a class-level attribute seems suitable.
When using a class, the benefit might be to combine the form display, view display and eventually some kind of data handling in one class?!
This might still be possible if an extra field plugin could live or be discoverable within the same (parent?) directory. Then something like this may be possible:
#[ExtraViewField(id: 'my_extra_field', entity_type: 'node')] #[ExtraFormField(id: 'my_extra_field', entity_type: 'node')] class MyExtraField implements PluginFormInterface, ExtraViewFieldInterface, ExtraFormFieldInterface { public function buildConfigurationForm(...); public function formElement(array &$element, array &$form, FormStateInterface $form_state): void { // $element has #weight already set and is already attached to $build['my_extra_field'] $element += ['#type' => 'details' ...]; } public function viewElement(array &$element, array &$build): void { // $element has #weight already set and is already attached to $build['my_extra_field'] $element += ['#type' => 'details' ...]; } }
However such implementation would be using the same buildConfigurationForm(...) for both view and form, not sure whether that might be a bad thing.
Anyway we may continue elaborating all this maybe in a separate issue as suggested by catch.
- πͺπΈSpain pcambra Asturies
Just chiming in to point to https://www.drupal.org/project/extra_field β and https://www.drupal.org/project/extra_field_plus β which might be useful in this context? happy to open a branch and give access if it's of any kind of use
- π©πͺGermany Anybody Porta Westfalica
Thanks @pcambra, same here!
With https://www.drupal.org/project/extra_field_plus β you add another important point for using a class:
Allow to add settings for extra fields (e.g. widget / display settings). Guess that should be handled by (inherited) methods.As @mxh wrote in #50 we should elaborate, where extra fields are placed and how they may interact with widgets and formatters. Maybe that also solves the settings partially. I agree extra fields might be a (yet missing) intermediate layer between the storage and the formatters / widgets.