1

I have a custom entity called "release". Release has "state" and "building percentage" fields, which values may change during the release process.

In both "setState" and "setPercentage" entity method I explicitly do the following:

$this->setChangedTime(time());
$this->save();

However, during the process, the "changed" column in the database always remains the same value. Am I missing something? What could be wrong?

UPDATE: Running the "setState" and "setPercentage" in a test script separated, the database gets updated.

UPDATE2:

I got it. "ChangedItem.php" - line 37, I logged there, and this is where it sets back to the request time value:

   // On an existing entity translation, the changed timestamp will only be
      // set to the request time automatically if at least one other field value
      // of the entity has changed. This detection does not run on new entities
      // and will be turned off if the changed timestamp is set manually before
      // save, for example during migrations or by using
      // \Drupal\content_translation\ContentTranslationMetadataWrapperInterface::setChangedTime().

will be turned off if the changed timestamp is set manually before save

This "promise" of the comment is definitely not working. Any suggestions?

  • Are you implementing EntityChangedInterface and also referencing EntityChangedTrait in your entity class (or extending from one that does so)? – Clive Jul 26 '16 at 12:51
  • Both, but good point! – ssibal Jul 26 '16 at 12:54
  • Hmmm, so you're not overriding setChangedTime in your own class? That's odd, it should work in that case – Clive Jul 26 '16 at 12:55
  • The funny thing is: am now logging to watchdog, when "setState" and "setPercentage" was called: \Drupal::logger('ifc_release')->info('Percentage time is: @time', array('@time' => $this->getChangedTime())); In logging, it shows the right value. In phpmyadmin: it doesn't give a shit about it. – ssibal Jul 26 '16 at 12:56
2

Okey I found the final reason:

ChangedItem.php

  $original = $entity->original;
      $langcode = $entity->language()->getId();
      if (!$entity->isNew() && $original->hasTranslation($langcode)) {
        $original_value = $original->getTranslation($langcode)->get($this->getFieldDefinition()->getName())->value;
        if ($this->value == $original_value && $entity->hasTranslationChanges()) {
         $this->value = REQUEST_TIME;
        }
      }

The conclusion:

In Drupal 8 if you save the same entity TWICE within 1 second (for whatever reason), you won't able to save your own changed time BUT it will be the REQUEST_TIME instead... wtf? ...

  • It doesn't ever save your value, it always saves the request time. That's exactly what changed is for. If you don't want that, use a timestamp field type, not changed. – Berdir Jul 26 '16 at 19:55
  • It saves your value, if the original entity "changed" value is different from the upcoming value HOWEVER if they are the same, the REQUEST TIME is going to be used, which can mean "the past" if it's a long process (like mine). What I will have to do, to avoid the possibility that it jumps back to request time, that, if the original and new value is the same (before saving) I will increase with +1 second, and it will work. – ssibal Jul 27 '16 at 7:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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