Score:1

Custom Entity "changed" field is unknown

cn flag

I'm having a problem I really don't know how to solve, and need your knowledge. I have a custom entity that someone created, and forgot to add the "changed" field. So the objective is to add this field, and updated all entities to set the "changed" field to be equal to the "created" field.

Somehow even if I've updated the entity inserting this changed field, the database shows it, and when dumping the entity this field exists, somehow when I try to set a value to it, it does show an error: enter image description here

I'll show what I've done to insert this field.

Inside the .module

function module_update_9012()
{
  $changed = \Drupal\Core\Field\BaseFieldDefinition::create('changed')
  ->setLabel(t('Changed'))
  ->setDescription(t('The time that the entity was last edited.'));
  
  \Drupal::entityDefinitionUpdateManager()
    ->installFieldStorageDefinition('changed', 'trialmachine_evaluation', 'trialmachine_evaluation', $changed);
}

Inside the Evaluation entity

use EntityChangedTrait;
public static function baseFieldDefinitions(EntityTypeInterface $entity_type)
{
     $fields = parent::baseFieldDefinitions($entity_type);
     //There are other fields, but they are not needed for this example.
     $fields['changed'] = BaseFieldDefinition::create('changed')
        ->setLabel(t('Changed'))
        ->setDescription(t('The time that the entity was last edited.'));
     return $fields;
}

I've also extended the ContentEntityBase and implemented the EvaluationInterface. While in the EvaluationInterface I've extended the ContentEntityInterface and EntityChangedInterface.

I added the changed to entity_keys on the annotations, and run drush cr to rebuild the cache, and everything.

Then, I'm trying to simply update the field programmatically using a route with a controller to test it. This is what I did:

$evaluations = \Drupal::entityTypeManager()->getStorage('trialmachine_evaluation')->loadMultiple();

if (!empty($evaluations)) {
   foreach ($evaluations as $item) {
      if (empty($item->changed->value)) {
         //$item->set('changed', $item->created->value);
         //$item->changed->value = $item->created->value;
         //$item->changed = $item->created->value;
         $item->setChangedTime($item->created->value);
         $item->save();
      }
   }
}

In this example there are commented lines to show what I've tried to do, but in any of these atempts the same error appeared.

Dump of the entity object. The data are '---' for privacy reasons, there are right data types in there.

object(Drupal\trialmachine_evaluation\Entity\Evaluation)[967]
  protected 'values' => 
    array (size=7)
      'id' => 
        array (size=1)
          'x-default' => string '---' (length=1)
      'user_id' => 
        array (size=1)
          'x-default' => string '---' (length=1)
      'campaign_id' => 
        array (size=1)
          'x-default' => string '---' (length=1)
      'order_id' => 
        array (size=1)
          'x-default' => string '---' (length=1)
      'answers' => 
        array (size=1)
          'x-default' => string '---' (length=66)
      'created_at' => 
        array (size=1)
          'x-default' => string '---' (length=19)
      'changed' => 
        array (size=1)
          'x-default' => null
  protected 'fields' => 
    array (size=0)
      empty
  protected 'fieldDefinitions' => 
    array (size=6)
      'id' => 
        object(Drupal\Core\Field\BaseFieldDefinition)[971]
          protected 'type' => string 'integer' (length=7)
          protected 'propertyDefinitions' => null
          protected 'schema' => null
          protected 'indexes' => 
            array (size=0)
              ...
          protected 'itemDefinition' => 
            object(Drupal\Core\Field\TypedData\FieldItemDataDefinition)[972]
              ...
          protected 'definition' => 
            array (size=7)
              ...
          protected 'typedDataManager' => null
      'user_id' => 
        object(Drupal\Core\Field\BaseFieldDefinition)[975]
          protected 'type' => string 'entity_reference' (length=16)
          protected 'propertyDefinitions' => null
          protected 'schema' => null
          protected 'indexes' => 
            array (size=0)
              ...
          protected 'itemDefinition' => 
            object(Drupal\Core\Field\TypedData\FieldItemDataDefinition)[976]
              ...
          protected 'definition' => 
            array (size=8)
              ...
          protected 'typedDataManager' => null
      'campaign_id' => 
        object(Drupal\Core\Field\BaseFieldDefinition)[979]
          protected 'type' => string 'entity_reference' (length=16)
          protected 'propertyDefinitions' => null
          protected 'schema' => null
          protected 'indexes' => 
            array (size=0)
              ...
          protected 'itemDefinition' => 
            object(Drupal\Core\Field\TypedData\FieldItemDataDefinition)[980]
              ...
          protected 'definition' => 
            array (size=7)
              ...
          protected 'typedDataManager' => null
      'order_id' => 
        object(Drupal\Core\Field\BaseFieldDefinition)[983]
          protected 'type' => string 'entity_reference' (length=16)
          protected 'propertyDefinitions' => null
          protected 'schema' => null
          protected 'indexes' => 
            array (size=0)
              ...
          protected 'itemDefinition' => 
            object(Drupal\Core\Field\TypedData\FieldItemDataDefinition)[984]
              ...
          protected 'definition' => 
            array (size=7)
              ...
          protected 'typedDataManager' => null
      'answers' => 
        object(Drupal\Core\Field\BaseFieldDefinition)[987]
          protected 'type' => string 'string' (length=6)
          protected 'propertyDefinitions' => null
          protected 'schema' => null
          protected 'indexes' => 
            array (size=0)
              ...
          protected 'itemDefinition' => 
            object(Drupal\Core\Field\TypedData\FieldItemDataDefinition)[988]
              ...
          protected 'definition' => 
            array (size=6)
              ...
          protected 'typedDataManager' => null
      'created_at' => 
        object(Drupal\Core\Field\BaseFieldDefinition)[990]
          protected 'type' => string 'datetime' (length=8)
          protected 'propertyDefinitions' => null
          protected 'schema' => null
          protected 'indexes' => 
            array (size=0)
              ...
          protected 'itemDefinition' => 
            object(Drupal\Core\Field\TypedData\FieldItemDataDefinition)[991]
              ...
          protected 'definition' => 
            array (size=7)
              ...
          protected 'typedDataManager' => null
  protected 'languages' => null
  protected 'langcodeKey' => string '' (length=0)
  protected 'defaultLangcodeKey' => string 'default_langcode' (length=16)
  protected 'activeLangcode' => string 'x-default' (length=9)
  protected 'defaultLangcode' => string 'und' (length=3)
  protected 'translations' => 
    array (size=1)
      'x-default' => 
        array (size=1)
          'status' => int 1
  protected 'translationInitialize' => boolean false
  protected 'newRevision' => boolean false
  protected 'isDefaultRevision' => boolean true
  protected 'entityKeys' => 
    array (size=7)
      'bundle' => string 'trialmachine_evaluation' (length=23)
      'id' => string '---' (length=1)
      'campaign_id' => string '---' (length=1)
      'answers' => string '---' (length=66)
      'user_id' => string '---' (length=1)
      'order_id' => string '---' (length=1)
      'created_at' => string '---' (length=19)
  protected 'translatableEntityKeys' => 
    array (size=0)
      empty
  protected 'validated' => boolean false
  protected 'validationRequired' => boolean false
  protected 'loadedRevisionId' => null
  protected 'revisionTranslationAffectedKey' => string 'revision_translation_affected' (length=29)
  protected 'enforceRevisionTranslationAffected' => 
    array (size=0)
      empty
  protected 'entityTypeId' => string 'trialmachine_evaluation' (length=23)
  protected 'enforceIsNew' => null
  protected 'typedData' => null
  protected 'cacheContexts' => 
    array (size=0)
      empty
  protected 'cacheTags' => 
    array (size=0)
      empty
  protected 'cacheMaxAge' => int -1
  protected '_serviceIds' => 
    array (size=0)
      empty
  protected '_entityStorages' => 
    array (size=0)
      empty
  protected 'isSyncing' => boolean false

Thanks for reading.

Score:1
de flag

When putting all the elements together, your code seems absolutely correct (I ran a few entity update tests and the update code doesn't need anything else).

Yet, when looking at the dump of your entity, I can see that there is no "fieldDefinitions" for the "changed" field. My best guess is that something went wrong when updating the entity schema.

Can you please elaborate on how you performed the update, please? When going to /admin/reports/status, do you see any Entity-related error?

Also, just to make sure:

  • is your Entity id "trialmachine_evaluation"? The namespace being Drupal\trialmachine_evaluation\Entity\Evaluation, I just wonder if the entity id is different.
  • you mentioned that the hook_update_N() is in .module file. I don't think it prevents the update script from running it, but it should be in a .install file.
Jean da Silva avatar
cn flag
Thanks for helping. To answer your questions: The entity id is "trialmachine_evaluation", but it also have the base_table as "trial_machine_evaluations". Also, I am using the hook_update_N() inside the .module because there were other hooks like this inside there, and because I think I can't reinstall this module. About the report_status, yeah, it is showing an error saying to uninstall the field "changed".
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.