Download & Extend

Make title behave as a field (again)

Project:Drupal core
Version:8.x-dev
Component:entity system
Category:feature request
Priority:major
Assigned:Unassigned
Status:postponed
Issue tags:D8MI, Entity system, language-content, translatable fields

Issue Summary

Title was (briefly) a field in the Drupal 7 development cycle but that was rolled back after active discussion in #571654: Revert node titles as fields. The contributed http://drupal.org/project/title module exists to make this happen for Drupal 7, but it is such a core piece that it needs to be cycled back to Drupal core in Drupal 8 if at all possible.

Comments

#2

In the Title module we are facing more or less the problems summarized in the other's issue OP and fully described in the attached spreadsheet: the approach taken follows a proposal by @chx to leave the $entity->label field as a plain property and override it at load time with the proper translation taken from $entity->label_field. This can work in contrib but it would be a horrible hack if it were in core. The main pro of this solution is that we don't need to care much about most of the problems cited above, the big con is that it's an inherently fragile approach that might break as soon as one needs to act before a translation is switched in. The storing process is even more convolute and failure prone, since we need to use the value in $entity->label on programmatic saves, but on the same time we need to use the value from $entity->label_field on submit, since the Field API widget is used to enter the translated value.

I still think that we should treat labels as regular fields, i.e. they should follow the usual field workflow to be displayed (load, build, render), instead of being slapped in the page through a simple check_plain($node->title). The main argument against this was that we want to be able to make a simple query to list entities by title, but in the real world we use Views and, if I'm not mistaken, Views perform an entity_load() to display entity lists, hence I don't see this as a performance regression.

Another concern was about DX: we have entity_label($entity_type, $entity) that is perfect for any use of labels outside the entitiy view context (breadcrumbs, administration pages, ...). Moreover, if what we talked about in the entity BOF in Chicago comes true, this will become $entity->label() which is simply beautiful from the DX perspective. Obviously we will need to be able to convert a field value in a plain string but I don't think this is a major probelm.

#3

Yes, I agree with @plach, let's work on figuring out how to make the label rendering simple, and transition back to using a full field. Sounds like the best solution overall.

#8

Priority:normal» major
Issue tags:+translatable fields

Can we move over one of the latest patches from the existing issue(s)?

As discussed in #1233394: Agree on a property naming pattern, retrieving an entity's title may no longer be a problem as tough as in D7, as it looks like we're going to move to proper entity classes as well as proper getter and setter methods for entity properties and fields.

Essentially, we also need to do the same for the author and status properties. Different issues, but pretty much the same challenge.

#9

Do you mean that getters/setters would provide an unified interface for both properties an fields? Actually very few persons chimed in in this issue and the parent one, so I wouldn't take for granted that entity labels are going to be fields.

Personally the approach outlined in http://groups.drupal.org/node/165194#comment-554029 looks the most viable to me. I'd like to read some feedback on it.

#10

@plach: on properties, fago had some good looking plans presented in London. See the video from 38th minute at http://london2011.drupal.org/coreconversation/unified-entity-api-part-co... (the talk before is also interesting to put it into perspective). Would be great to figure out how do we want to achieve our translatable properties :) @fago's point is that properties should look the same from the outside as fields on the API level.

#13

#14

#16

Anybody want to work on this? It would be great to continue work here sooner than later.

#17

I think this should be totally postponed to finding a solution for translatable entity properties.

#18

@plach: well, title as a field maybe could mean I can add a date field as title and/or remove title field? If title is a property and that solves translatability (and we don't want / need the additional flexibility of it being a field), then we might not want to to do this I guess. In that case, this would be a won't fix. So far I was hearing it is that either title is going to be a field or it is going to be a translatable property. Do you have an issue number for translatable properties (and/or its pre-requisites?). This is a very critical part of Drupal 8's multilingual system.

#19

I really think it should be a field. I've been in the situation Gábor mentions above where I don't want a text field for the title. I'd rather have an integer/date/etc.

Maybe we can find a quick route / fall-back to getting the default language's title in a hurry without going through the translation system (to keep that query simple)?

#20

@plach: could you put the issue(s) of the translatable entity properties?

We shouldn't wait for translatable entity IMHO, since we can do this one, then maybe open a followup issue for that + we can also follow the same approach for other stuff like author.

Also, we need an update path tag, don't we?

I'll try to work on this very soon.

#21

Some thoughts on how to do this if we do make it a field:

1. make it either its own field type which is UI-locked, or a particular text field which is created by core on install
2. introduce something in hook_entity_info() where entities can specify fields they have built-in. Therefore most core entities will demand a title field, and it can't be removed by the user.
3. to get round the performance problems, add a second field storage module to core that stores single-valued fields as columns in the entity table.

#22

Issue tags:+Entity system

#23

Issue tags:+language-content

Tagging for the content handling leg of D8MI.

#24

Title should be a translatable property - #1498634: [meta] Define revision/translation SQL schema for core entities (no patch)
Suppose this issue should be commited before #1498674: Define node translation schema

#25

I think this issue title and summary is too vague. In #1346214: [META] Entity Property API, the goal for D8 is for all properties to behave like fields in some ways. Is there some sense in which title needs to be even more field-like than what's covered by that issue? Or nervousness about the risk we won't finish that issue in D8?

Also, I commented on #1498674-4: Define node translation schema that I don't think this issue should hold up that one.

#26

AFAIK, "making properties behave like fields in some ways" is about letting properties to use widgets and formatters.

FWIW, this is precisely where I'm at in my ongoing "OO/plugins field API" work; read : I didn't start that part yet, but this is probably the goal that will provide a direction for the shape of the API now - decouple widgets and formatters from "fields" (and right now I'm not sure how this is going to work, because widgets and formatters currently rely on $field['some_arbitrary_property']).

This being said, once/if
- widgets and formatters can act on properties and fields alike,
- Entity-level storage engines take care of storing entities as a whole (properties + fields) (#1497374: Switch from Field-based storage to Entity-based storage),
then it's not really clear to me what the actual difference between fields and properties will be...

#27

then it's not really clear to me what the actual difference between fields and properties will be

From what I can tell, even in #1497374: Switch from Field-based storage to Entity-based storage, fields can still be:

  • Multi-valued
  • Shared across multiple entity types/bundles (at least across those that use the same storage backend)

I think those are the distinguishing ways in which fields are more feature-rich properties. Those requirements lead naturally to storing fields in per-field rather than per-bundle tables when using sql storage (core's default). And I think that default storage decision leads naturally to a desirability (for performance) to sometimes load $partial_entity objects (containing all properties but no fields), which leads to a bias to making properties that are seen as fundamental to the underlying nature of the entity as properties rather than fields (and traditionally, node title has fallen into this category).

We also currently have a UI for administrators to add fields, but not properties, and while when a property API is in place, nothing will prevent us from expanding that UI to allow administrator-created non-field properties, I don't know that anything will compel us to do so either.

#28

I think I misstated the second bullet point in #27. Here's the correction. Even after all current entity system improvements planned for D8 that I'm aware of are in place, fields will have the following features that distinguish them from non-field properties:

  1. They can be multi-valued. For example, you can set field_image (the one created as part of core's standard profile install) to have "number of values" to something >1, and then proceed to add more than one image to that field.
  2. They can be shared across multiple entity types. For example, while core's standard profile adds field_image to nodes only, you can also add that same field to comments and taxonomy terms, and then with some custom code, query for all nodes, comments, and taxonomy terms that have a certain image in that field.
  3. They can be *not* shared across bundles. For example, core's standard profile adds field_image to the Article node type, but not to the Page node type.

There's some discussion in #1497374: Switch from Field-based storage to Entity-based storage about how important #2 is to keep. In practice, sharing the same field across entity types doesn't accomplish much, especially with Views not capable of querying across entity types.

One can also make a claim that #3 doesn't need to be a requirement of the storage system, but can be implemented at an API level (e.g., if a storage engine wanted to add field_image to the {node} table, then the column would exist for Page nodes too, but the Entity API could be made to ensure that modules and the UI behave as though the field only exists for Article nodes).

So, *if* we were to drop #2 and #3 as concerns, then potentially the only remaining difference between properties and fields is support for multiple values. In which case, maybe it'll make sense for us to change terminology to discussing single-valued vs. multi-valued properties and drop "field" as a concept entirely.

#29

One difference between properties and fields that has not been mentioned yet is that fields may be multi-columned: in D7 Title provides an API to replace properties with fields but cannot perform the mapping automatically because it has no way to tell which is the column (columns?) holding the value to be put in the plain property. I think the difference between the two may be summed up in the fact that fields may be multiple compound values, while in D7 properties are essentially single values. Yes, they can hold arrays being serialized at storage time but I'd say this is an edge case.

However, @effulgentsia is raising valid points to be discussed in #28 but I feel this issue should specifically focus on the label topic. AAMOF while labels are currently properties, they also have a whole bunch of specific usages that plain properties don't need to care for: depending on the context a label may be used as an administrative item (e.g. admin-side entity listing), a navigational item (e.g. breadcrumb) or pure content, possibily containing markup (e.g. page title). Not every entity type might need the last two usages, while the first one is probably required. The first two usages require a plain text value, while the third might accept a rendered value.

The default label implementation could be backed by a (translatable) property, but we might introduce the possibilty to designate a field as a "label provider" instead of the plain property. The Entity interface should expose a method to get the entity label as a plain string, it should be responsibility of the label provider to implement a to-string functionality. We should retain the capability of having computed labels (in D7 we have the 'label callback' in entity_label()), which might not even need to be translated. For instance, an event date might just need to be localized on the fly, but a value shared among all the entity translations should be enough. This flexiblilty should free us from requiring an actual storage column for the label, which would be available only where it actually makes sense. In this scenario, the pure content behavior could be implemented on a per-entity type basis, if ever needed.

#30

@plach suppose in any case we need a some config storage (or just code) to configure a callback. For example title could be biulded from tokens so label callback should use some config/variable per entity(type) to store this setting

#31

@plach suppose in any case we need a some config storage (or just code) to configure a callback. For example title could be biulded from tokens so label callback should use some config/variable per entity(type) to store this setting

I was not arguing that we should keep the label callback in place, I was simply saying that we need to keep the ability to have a compute label for the uses cases mentioned above. Maybe simply overriding the Entity::label() method would be fine. As an alternative, we might use computed properties, possible?

#32

The answers to "how will fields be different from properties" so far (namely: a field can be multivalued, multicolumned, & doesn't necessarily appear on every bundle within the entity type) focus on 'features / behavior seen from the outside'. I was more thinking in terms of inner implementation/representation and performance.

If fields & properties storage is managed by the same entity storage provider, and both are displayed through widgets and formatters, then I'm not sure how properties remain more lightweight (memory and CPU-wise) than fields - which was the main reason to keep to separate concepts initially.

#33

Also, on the list of usages "kind of" specific to node title, I'd like to add autocomplete lookup.
The current label() callback, that implies that node titles can only be determined at runtime after load, basically forbids any autocomplete mechanism - see #1194086-42: Real Name not working for user references

#34

I think the difference between the two may be summed up in the fact that fields may be multiple compound values, while in D7 properties are essentially single values. Yes, they can hold arrays being serialized at storage time but I'd say this is an edge case.

I'd not say so. First off, properties would not be restricted to be single-valued as they are not restricted to live in the entity base table at all. That would be what our base-sql implementation handles, but that does not mean you are restricted to that. It would be completely fine to create your own special table for a special property just as we currently do for fields + expose it as regular entity property.

Thus, the whole point is that API-wise there is no distinction between a field and a property, i.e. fields are just properties added in by the field module.

That would help with the label problem a lot too I guess. Just annotate which property should serve as label, so it could point to a field as well (as it's just a property too). Thus migrating the label over from a basic-property to a field would be easy.

I think the difference between the two may be summed up in the fact that fields may be multiple compound values, while in D7 properties are essentially single values. Yes, they can hold arrays being serialized at storage time but I'd say this is an edge case.

Nope. Storage is handled as however the storage controller does. That might be a serialized data dump, a plain file, mongo-db or sql tables. By unifying the controller that's true for both, fields and properties.

For that to work, we'd have to provide a notion of storage controllers being "extendable", thus allowing modules to dynamically add stored properties. So field.module (as well as others) could make use of that to add its stuff. That's something we'll have to solve as part of the unified storage controller movement though.

If fields & properties storage is managed by the same entity storage provider, and both are displayed through widgets and formatters, then I'm not sure how properties remain more lightweight (memory and CPU-wise) than fields - which was the main reason to keep to separate concepts initially.

As said, I'd see the distinction between a property and a field solely as a question of control. So a field would be nothing else than a property controlled by field module. The very same way field module and via the field UI the user takes over the control of how a field is rendered / edited.
In contrast to that a regular module provided property (node.status, node.type, ..) is controlled by the module only, and its display and edit mode is too.

So, if field formatters and widgets would be just based upon property information + config it should be possible to manually invoke the same plugins as used for rendering/editing fields (as they are all just properties..).

#35

If fields & properties storage is managed by the same entity storage provider, and both are displayed through widgets and formatters, then I'm not sure how properties remain more lightweight (memory and CPU-wise) than fields - which was the main reason to keep to separate concepts initially.

1. If Drupal's default storage implementation is for a SQL database, and involves having entity tables (like {node}), and stores some single-valued properties in columns on the entity table, then entity queries limited to just those properties can be performed without an expensive JOIN. Per #33, autocomplete is one of many examples where we want entity label / node title to benefit from this.

2. If some single-valued properties can be rendered without the theme('field') wrapper (or use a variant of it designed for single-valued), they can be rendered faster, even if they use the same item formatter.

So, while we can evolve the entity system to a point where the terminology/concepts of property vs. field go away or are significantly changed, I think our experience in recognizing that some properties are better candidates for being single-valued and by default stored in the entity table, still applies. Maybe that will go away once Drupal's default entity storage engine is not SQL based, but I don't think that'll happen in D8.

#36

Back to this issue's title and scope: Gabor/plach: given that yched is currently working on pluginizing Field API to allow widget and formatter reuse to properties not managed by field.module, and fago (and others) are currently working on Entity API improvements to unify properties and fields as the same at an API level, but that both of those efforts are large and could take some time to fully land in core, what are you wanting out of this particular issue for D8MI work to proceed smoothly?

#37

@effulgentsia: we don't need this issue if done we can solve translating any property in other ways. We can just as well move on to #1498634: [meta] Define revision/translation SQL schema for core entities (no patch) which is the current discussion for property translation. I think @sun believed that title should be a field in any case, so we did not close this one, but we are really interested in one good way to translate title. If we have property translation in additionally to field translation, whether title is a property or field is just a technicality.

#38

Status:active» postponed

In that case, postponing this. But if someone has a reason to unpostpone it, please do.

#39

If we have property translation in additionally to field translation, whether title is a property or field is just a technicality.

From the D8MI perspective I fully agree.

In that case, postponing this. But if someone has a reason to unpostpone it, please do.

Well, this issue is not specifically about label translation: here we have a good chance to define more precisely what an entity label is and how it is supposed to work, which in my mind is more or less covered by #29. I'd like to reopen this once we have a proper Entity storage API in place, which should enable us to address the issues cited above in a storage-safe fashion.