Problem/Motivation
#2997123: Cacheability of normalized computed fields' properties is not captured during serialization added the ability for computed field properties to contribute cacheable metadata to the normalization. However, entity reference fields are treated totally different by json:api module, since they must be converted to a "Relationship object" which references a UUID and resource type. As a result, there is no way for computed ER fields to express cache metadata.
Updated: We must also account for cacheability of empty fields.
Steps to reproduce
Create a computed ER field on an entity and observe it cannot vary by cache tags, context or TTL.
Proposed resolution
Use similar logic to the recently-added feature set, but for ER fields. We can use ResourceIdentifier::getDataReferencePropertyName()
to be consistent.
Remaining tasks
Extend test coverage.
User interface changes
None.
API changes
None... well, we potentially change the visibility of the helper static method for getting the data reference property.
Data model changes
None.
Release notes snippet
TBD.
Original report
Hi,
I'm having an issue with a computed field (entity reference type) being displayed on JSON:API resources. The problem is that it's always cached, although it should change as I change for ex. categories or tags.
What I want is to have a computed/virtual field with similar articles for given article (depending on common categories and tags). For retrieving similar articles I use module called Similar By Terms => https://www.drupal.org/project/similarterms I want these similar articles to be outputted on JSON:API resources... and it works good, but it's cached all the time.
Here's my code:
function my_module_entity_bundle_field_info_alter(array &$fields, EntityTypeInterface $entityType, string $bundle): void {
if ($entityType->id() === 'node'&& $bundle === 'article') {
$fields['field_similar_articles'] = BaseFieldDefinition::create('entity_reference')
->setName('field_similar_articles')
->setLabel('Similar articles')
->setTargetEntityTypeId('node')
->setTargetBundle('article')
->setComputed(TRUE)
->setRevisionable(FALSE)
->setTranslatable(FALSE)
->setCardinality(FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED)
->setClass(SimilarArticlesComputedField::class);
}
}
class SimilarArticlesComputedField extends EntityReferenceFieldItemList {
use ComputedItemListTrait;
protected function computeValue(): void {
$similarArticles = <array of articles' entities get from the view>
foreach ($similarArticles as $key => $similarArticle) {
$this->list[$key] = $this->createItem($key, $similarArticle);
}
}
}
As I said, JSON:API resource displays field_similar_articles
field correctly, but when I change some article's category or tag then output of this field in JSON:API resource should change as well, but it's not.
Let's say there is Article 1, 2, 3, 4 and 5.
Article 2, 3 and 4 are similar articles to the Article 1 (because they share common tags/categories).
When I go to this resources /jsonapi/node/article/{article-1-uuid}
then I can see Article 2, 3 and 4 in section field_similar_articles
and also in included
section.
So far, so good.
But then, let's say that I delete tags and categories for Article 2 and once again go to the upper mentioned resource... I still can see Article 2, 3 and 4 in section field_similar_articles
... but Article 2 should not be there. What's interesting, in the included
section Article 2 disappears, which is good.
Could you please tell me what I can do about it ... and will it be possible after applying this patch (I'm using Drupal ver 9.2.10) from this issue?