6

I have a custom entity (Person) with these fields: ID, nom, prenom, telephoneportable, estactive, userID, created, changed. I created it with baseFieldDefinitions.

I want to have a computed field nomprenom = nom ." ".prenom
Here is the corresponding code:

$fields['nomprenom'] = BaseFieldDefinition::create('string')  
  ->setLabel(t('Nom et Prénom'))  
  ->setComputed(TRUE)  
  ->setClass('\Drupal\association\NomPrenom');  

The code of class 'NomPrenom' is here:

/**
 * @file
 * Contains \Drupal\association\NomPrenom.
 */

namespace Drupal\association;

use Drupal\Component\Utility\String;
use Drupal\Core\TypedData\DataDefinitionInterface;
use Drupal\Core\TypedData\TypedDataInterface;
use Drupal\Core\TypedData\TypedData;

/**
 * A computed property for defining 'Nom Prénom'.
 */
class NomPrenom extends TypedData {

  /**
   * Cached processed value.
   *
   * @var string|null
   */
  protected $processed = NULL;

  /**
   * Implements \Drupal\Core\TypedData\TypedDataInterface::getValue().
   */
  public function getValue($langcode = NULL) {
    if ($this->processed !== NULL) {
      return $this->processed;
    }

    $this->processed = $this->get('nom')->value ." ". $this->get('prenom')->value;
    return $this->processed;
  }

  /**
   * Implements \Drupal\Core\TypedData\TypedDataInterface::setValue().
   */
  public function setValue($value, $notify = TRUE) {
    $this->processed = $value;

    // Notify the parent of any changes.
    if ($notify && isset($this->parent)) {
      $this->parent->onChange($this->name);
    }
  }

}  

When I try to add a new Person, I get a PHP Fatal error:

Call to undefined method Drupal\association\NomPrenom::setLangcode()

Why?

3 Answers 3

0

I found this in ContentEntityBase.php 499 (but you could show us the whole error log):

I think the case is the following: your field is translatable (you didn't set it's not, and I tihnk the default is TRUE).

else {
  $field_langcode = $langcode;
}
**$field->setLangcode($field_langcode);**
$this->fields[$name][$langcode] = $field;

What I don't understand here: how basefield definition allows you to add a class which doesn't inherit / implements the right class / interface. I think it's a core bug?

You should either: - add set language method, with a languagecode property - set your computed field untranslatable

1
  • I have the same problem, but even when I use setTranslatable(FALSE) on the BaseFieldDefinition, I get the same error.
    – Hendrik
    Sep 25, 2016 at 18:48
0

I guess you were following the examples in this article: https://www.drupal.org/node/2112677

Note that one major difference is that the above article talks about computed properties in a (custom) field type, whereas you are trying to use a computed property in a custom entity. I don't know whether the latter is possible – I would like to know that myself.

However, from the above I expect that there is a feasible workaround that you could use: define a custom field type (e.g. called name) that defines two regular stored fields (firstname and lastname), as well as one computed property (fullname). You should then be able to create an instance of this field type in your entity's baseFieldDefinitions().

2
  • It's definitely possible to add a computed field to a custom entity type. The article unfortunately starts with an example that shows a custom property on a field, but what's actually implemented is a computed field on a custom entity ("profile").
    – Narretz
    Jun 30, 2017 at 16:38
  • This article might be helpful: cornel.co/article/… It shows a complex example how to use this on entities. Dec 7, 2023 at 17:09
0

The problem lies probably in the definition:

$fields['nomprenom'] = BaseFieldDefinition::create('string')  
  ->setLabel(t('Nom et Prénom'))  
  ->setComputed(TRUE)  
  ->setClass('\Drupal\association\NomPrenom');  

The example on Drupal.org isn't very clear here, but setClass is not the class that computes the value. setClass is the ItemList class that is defined later in the article to work around a bug in core (\Drupal\mymodule\CurrentCompanyLinkItemList).

The matching of the field definition and the class happens in BaseFieldDefinition::create('my_new_field'). This should be a unique identifier for your new field, not simply string etc.

In your class, you set the same as the id in the FieldType annotation:

 * @FieldType(
 *   id = "my_new_field",
 *   ...
 * )

Also note that the class that implements the FieldType must be in this namespace:

namespace Drupal\my_module\Plugin\Field\FieldType;

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.