6

My module provides config that creates a field:

field.storage.paragraph.field_accordion_section_title.yml

langcode: en
status: true
dependencies:
  module:
    - paragraphs
    - text
id: paragraph.field_accordion_section_title
field_name: field_accordion_section_title
entity_type: paragraph
type: text_long
settings: {  }
module: text
locked: false
cardinality: 1
translatable: true
indexes: {  }
persist_with_no_fields: false
custom_storage: false

I would like to update the field to use string_long instead of text_long. I would like to handle this via hook_update() since the module was already installed on multiple sites. I tried the following:

use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;

/**
 * Updates accordion section title to string type.
 */
function my_module_update_8001() {
  if ($fields = \Drupal::entityTypeManager()->getStorage('field_storage_config')->loadByProperties(array('field_name' => 'field_accordion_section_title'))) {
    foreach ($fields as $field) {
      $new_field = $field->toArray();
      $new_field['type'] = 'string_long';
      $new_field = FieldStorageConfig::create($new_field);
      $new_field->original = $field;
      $new_field->enforceIsNew(FALSE);
      $new_field->save();
    }
  }
}

I get the following error when updating: Failed: Cannot change the field type for an existing field storage.

2
  • Since you are calling enforceIsNew(FALSE), you are forcing Drupal not to consider it a new field. Did you try with enforceIsNew(TRUE)? I would also avoid using $new_field->original = $field; because that is telling Drupal that the field is being updated.
    – apaderno
    Jan 19, 2017 at 22:04
  • I tried it but got back: Failed: 'field_storage_config' entity with ID 'paragraph.field_accordion_section_title' already exists.
    – albertski
    Jan 19, 2017 at 22:15

2 Answers 2

6

As the error message says, this is not supported. There is no API that will do it for you.

There was a similar question recently but I can't find it right now, just this one: How do I change the type of a field attached to a content entity?

In short, you have two options:

  1. Create a new field, write a script to move over all your data, then delete the old field.
  2. Manually alter the database schema and low-level config data as well as the data that Drupal has stored about the field type and its schema. This is by far the more complicated option.
1

Expanding on @Berdir answer, I would recommend option 1. Creating a separate field, migrating the data and deprecating the old field (not necessarily deleting it, just in case)

For example, let's say your Paragraphs (can be Nodes) of type "sample" have a field "body" that is currently plain text (plain, long) and you want it to be rich text (formatted, long)

  1. Create the new field in Drupal admin
  2. Add the update

    /**
     * Update paragraph body to rich text
     */
    function es_updates_update_8117() {
      $paragraphs = \Drupal::entityTypeManager()->getStorage('paragraph')->loadByProperties(['type' => 'sample']);
      foreach ($paragraphs as $paragraph) {
        $paragraph->field_body_rich->value = $paragraph->field_body->value;
        $paragraph->save();
      }
    }
    
  3. Remember to update your twig templates to reflect the change of field name if needed.

  4. Remember to optimize it for authors, such as:
    • Rename the old field (in my case I added "[DEPRECATED]" to the label)
    • Move the old field in Form Display to the Hidden section
    • Move the old field in View Display to the Hidden section
  5. Finally, once you've proved everything works as expected with the new field, feel free to remove it.

Your Answer

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

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