- Issue created by @seth.e.shaw
- πΊπΈUnited States seth.e.shaw
I should have also noted that we are running on MySQL 8.0.
- πΊπΈUnited States oadaeh
I created an update hook that uses guidance from this SE answer:
https://drupal.stackexchange.com/questions/208946/how-do-i-change-a-fiel...It requires some manual set up operations, so I don't know that this could be included as a generic update for the module, but if someone wanted to explore that, this should help them quite a bit.
Start with a backup and practice on a development copy of the site to convert. You will probably need to rebuild the site from the database backup a few times before you get your finished product.
Follow the steps in that SE post.
You need to modify the config of the fields, and that is done by deleting and recreating the fields, exporting them, then changing the UUIDs back to what the original fields were. What you are targeting is updating the config of the existing fields, not creating new ones, but you might need to manually delete and create them to know what config changes need to be made. You could also manually modify the files, if you know what needs to be changed.
When you are done, you should have an update hook and modified config that will convert your site with a drush deploy command
Here is my code, which differs slightly from the code in the post:
function custom_module_update_1234() { $database = Drupal::database(); $fields = [ 'node' => [ 'field_fieldname1', ], 'block_content' => [ 'field_fieldname2', 'field_fieldname3', ], ]; foreach ($fields as $entity_type => $field_names) { foreach ($field_names as $field_name) { \Drupal::logger('custom_module_update')->debug('Converting ' . $entity_type . '__' . $field_name . ' from JSON/JSONB to JSON Field.'); $field_storage = FieldStorageConfig::loadByName($entity_type, $field_name); if (is_null($field_storage)) { return; } // Include the revisions as well. $tables = [ $entity_type . '__' . $field_name, $entity_type . '_revision__' . $field_name, ]; $rows = []; foreach ($tables as $table) { $rows[$table] = NULL; } // Store the data to restore after the update is completed. foreach ($tables as $table) { if ($database->schema()->tableExists($table)) { $rows[$table] = $database->select($table, 'e') ->fields('e') ->execute() ->fetchAll(); } } $new_fields = []; // Use existing field config for new field. foreach ($field_storage->getBundles() as $bundle => $label) { $field = FieldConfig::loadByName($entity_type, $bundle, $field_name); $new_field = $field->toArray(); $new_field['field_type'] = 'json_native'; $new_field['settings'] = []; $new_fields[] = $new_field; } // Deleting field storage which will also delete bundles(fields). $new_field_storage = $field_storage->toArray(); $new_field_storage['type'] = 'json_native'; $field_storage->delete(); // Purge field data now to allow new field and field_storage with same name // to be created. (The batch size might need to be increased.) field_purge_batch(10); // Create new field storage. $new_field_storage = FieldStorageConfig::create($new_field_storage); $new_field_storage->save(); // Create new fields. foreach ($new_fields as $new_field) { $new_field = FieldConfig::create($new_field); $new_field->save(); } // Restore existing data in the same table. foreach ($tables as $table) { if (!is_null($rows[$table])) { foreach ($rows[$table] as $row) { $database->insert($table) ->fields((array)$row) ->execute(); } } } } } }
- Status changed to Closed: outdated
5 months ago 4:23pm 19 April 2024 - πΊπΈUnited States seth.e.shaw
I should have come back and posted what I ended up doing...
These were the steps taken:
- Install json_field:
composer require drupal/json_field
- Enable the module:
drush {site url} en -y json_field
- Clear cache:
drush {site url} cr
- Run the update script (below):
drush scr ~/update.php
- Uninstall jsonb:
drush pm:uninstall -y jsonb
- Remove jsonb:
composer remove drupal/jsonb
Update script:
<?php /** * @file */ if (!$field_storage_configs = \Drupal::entityTypeManager()->getStorage('field_storage_config')->loadByProperties(['type' => 'json'])) { return; } foreach ($field_storage_configs as $field_storage) { $new_field_storage = $field_storage->toArray(); $new_field_storage['type'] = 'json_native'; $new_field_storage['module'] = 'json_field'; $new_field_storage = \Drupal::entityTypeManager()->getStorage('field_storage_config')->create($new_field_storage); $new_field_storage->original = $new_field_storage; $new_field_storage->enforceIsNew(FALSE); $new_field_storage->save(); $field_name = $field_storage->getName(); if (!$fields = \Drupal::entityTypeManager()->getStorage('field_config')->loadByProperties(['field_name' => $field_name])) { continue; } foreach ($fields as $field) { $new_field = $field->toArray(); $new_field['field_type'] = 'json_native'; $new_field['dependencies']['module'] = 'json_field'; $new_field = \Drupal::entityTypeManager()->getStorage('field_config')->create($new_field); $new_field->original = $field; $new_field->enforceIsNew(FALSE); $new_field->save(); // Update view displays. $properties = [ 'targetEntityType' => 'node', 'bundle' => 'asu_repository_item', ]; if ($view_displays = \Drupal::entityTypeManager()->getStorage('entity_view_display')->loadByProperties($properties)) { foreach ($view_displays as $view_display) { if ($component = $view_display->getComponent($field_name)) { $view_display->setComponent($field_name, [ 'type' => 'json', ] + $component); $view_display->calculateDependencies(); $view_display->save(); } } } // Update form displays. if ($form_displays = \Drupal::entityTypeManager()->getStorage('entity_form_display')->loadByProperties($properties)) { foreach ($form_displays as $form_display) { if ($component = $form_display->getComponent($field_name)) { $form_display->setComponent($field_name, [ 'type' => 'json_textarea', ] + $component); $form_display->calculateDependencies(); $form_display->save(); } } } } }
- Install json_field: