Drupal - 필드 유형 마이그레이션

30815 단어 drupalphpdatabase
서로 다른 필드 유형 간에 데이터를 이전하는 데는 여러 가지 방법이 있는데, 본 간략한 소개는 가능한 방법을 설명할 것이다.

Field is a Drupal core module and it’s part of a list of different ways to represent data in Drupal.


이 절차에는 다음이 포함됩니다.
  • 사용자 정의 모듈을 만듭니다.
  • 이동 변수를 준비합니다.
  • 기존 데이터를 저장합니다.
  • 필드 구성 저장소를 가져옵니다.
  • 필드 구성을 가져옵니다.
  • 이전 구성을 삭제합니다.
  • 새 필드 구성에 데이터를 삽입합니다.
  • (즉, 데이터베이스 업데이트) 마이그레이션을 실행합니다.

    선결 조건

  • 신규 또는 기존 Drupal 9.0 프로젝트.
  • Drush CLI 도구composer require drush/drush
  • 명심해야 할 일

  • 이 연습에서는 필드를 숫자(정수)에서 텍스트(포맷)로 변환합니다.See documentation for list of field types .
  • 1 - 사용자 정의 모듈 만들기
    Drupal에서 사용자 정의 모듈을 만들 수 있습니다abundant list of documentations.그러나 우리가 사용하는 최소 폴더 구조는 다음과 같습니다.
    field_migration_medium/
      field_migration_medium.info.yml
      field_migration_medium.install
    
    field_migration_medium 파일에서 이 사용자 정의 모듈의 기존 데이터베이스 업데이트를 Drupal에 알리기 위해 field_migration_medium.install function 를 사용합니다.
    <?php
    /**
    * hook_update_N()
    */
    function field_migration_medium_update_9001() {
    }
    

    N donates the update ID and Drupal keeps track of this for each module. See the documentation for more info.


    2 - 마이그레이션 변수 준비
    현재 필드 형식과 새 필드 형식을 식별해야 합니다.이러한 값을 식별하기 위해서 우리는 Field Config StorageField Config의 의미를 이해해야 한다.
    Drupal의 bundle 은 숫자, 텍스트, 부울 값 등 다양한 필드 유형으로 구성되어 있습니다. 이 필드 유형 중 하나는 기본 설정 Field Storage Configuration 과 특정한 설정 Field Configuration 이 있습니다.
    예를 들어 저는 세 가지 다른 내용 유형hook_update_N, field_number, article을 만들었습니다.이 모든 내용 유형은 같은 page 전역 설정을 공유하지만, 모든 내용 유형은 자신의 실현과 기본 설정medium을 가지고 있다.
    이러한 차이점을 설명하기 위해 다음은 각 객체의 세그먼트 (필드 저장 구성 및 필드 구성) 입니다.

  • 글로벌 구성: 필드 스토리지 구성 객체field_number.
  • Drupal\field\Entity\FieldStorageConfig Object                                
      (                                                                            
          [id:protected] => node.field_number                                      
          [field_name:protected] => field_number                                   
          [entity_type:protected] => node                                          
          [type:protected] => integer                                              
          [module:protected] => core
    

  • 구체적인 구성: field_number 내용 유형의 필드 구성 대상.
  • Drupal\field\Entity\FieldConfig Object                                
      (                                                                            
          [deleted:protected] =>                                                   
          [fieldStorage:protected] =>                                              
          [id:protected] => node.article.field_number                              
          [field_name:protected] => field_number                                   
          [field_type:protected] => integer                                        
          [entity_type:protected] => node                                          
          [bundle:protected] => article                                            
          [label:protected] => Number                                              
          [description:protected] =>                                               
          [settings:protected] => Array                                            
              (                                                                    
                  [min] =>                                                         
                  [max] =>                                                         
                  [prefix] =>                                                      
                  [suffix] =>                                                      
              )
    

  • 구체적인 구성: field_number 내용 유형의 필드 구성 대상.
  • pageDrupal\field\Entity\FieldConfig Object                                   
      (                                                                            
          [deleted:protected] =>                                                   
          [fieldStorage:protected] =>                                              
          [id:protected] => node.page.field_number                                 
          [field_name:protected] => field_number                                   
          [field_type:protected] => integer                                        
          [entity_type:protected] => node                                          
          [bundle:protected] => page                                               
          [label:protected] => Number                                              
          [description:protected] =>                                               
          [settings:protected] => Array                                            
              (                                                                    
                  [min] => 0                                                       
                  [max] => 11                                                      
                  [prefix] =>                                                      
                  [suffix] =>                                                      
              )
    

  • 구체적인 구성: article 내용 유형의 필드 구성 대상.
  • mediumDrupal\field\Entity\FieldConfig Object                                 
      (                                                                            
          [deleted:protected] =>                                                   
          [fieldStorage:protected] =>                                              
          [id:protected] => node.medium.field_number                               
          [field_name:protected] => field_number                                   
          [field_type:protected] => integer                                        
          [entity_type:protected] => node                                          
          [bundle:protected] => medium                                             
          [label:protected] => Number Text                                         
          [description:protected] => This is medium number text.                   
          [settings:protected] => Array                                            
              (                                                                    
                  [min] =>                                                         
                  [max] =>                                                         
                  [prefix] =>                                                      
                  [suffix] =>                                                      
              )
    

    There are subtle changes in each content type, such as id, bundle, label, description and settings. The common values in these content types are field_name, field_type and entity_type.


    이 점을 기억하고 이동 변수를 계속 정의합시다.
    마이그레이션 변수는 다음과 같습니다.
  • 솔리드 유형 - page.
  • 이전 _ 필드의 기계 이름입니다.기계 이름은 medium 에서 찾을 수 있습니다.이 필드를 node 라고 합니다.
  • 데이터베이스의 이전 _ 필드의 테이블 이름입니다.테이블 이름은 엔티티 이름과 이전 _ 필드 기계 이름/admin/reports/fields으로 구성됩니다.
  • old_필드의 수정표;존재하면또한 이전 _ 필드의 엔티티 이름과 기계 이름도 있습니다.field_number
  • 새 필드 구성을 저장하는 그룹
  • $entityType = 'node'; 
    $oldFieldName = 'field_number';
    $table = $entityType. '__' . $oldFieldName;
    $revisionTable = $entityType. '_revision__' . $oldFieldName;
    $newFieldsArray = [];
    
    3 - 스토리지에 데이터 및 개정 데이터 저장
    $rows = NULL;
    $revisionRows = NULL;
    if ($database->schema()->tableExists($table)) {
        $rows = $database->select($table, 'n')->fields('n')->execute()->fetchAll();
        $revisionRows = $database->select($revisionTable, 'n')->fields('n')->execute()->fetchAll();
    }
    
    4 - 현장 스토리지 구성 가져오기
    단일 필드 스토리지 구성이 있으므로 node__field_numbernode_revision__field_number$entityType method 로 전달하여 구성을 로드해야 합니다.
    $fieldStorage = FieldStorageConfig::loadByName($entityType, $oldFieldName);
    
  • 새로운 현장 스토리지 구성 정의
  • $newFieldStorage = $fieldStorage->toArray();
    $newFieldStorage['type'] = 'text';
    $newFieldStorage['settings'] = array(
       'max_length' => 255
    )
    

    Note: To get a list of the bundles that uses the field storage config, getBundles() method can be called like this $fieldStorage->getBundles() as we will see below.


    5 - 필드 구성 가져오기
  • 포함 $oldFieldName 가방을 모두 가져오고 교체합니다.
  • loadByName($entity_type_id, $field_name)
  • foreach ($fieldStorage->getBundles() as $bundle => $label) {
        $field = FieldConfig::loadByName($entityType, $bundle, $oldFieldName);
        // Turn the result into an array
        $newField = $field->toArray();
        // Update the field_type from `number` to `text`
        $newField['field_type'] = 'text';
        // Update the settings of this new field -- Optional
        $newField['settings'] = array(
               'max_length' => 255
        );
        // Store the result into an array
        $newFieldsArray[] = $newField;
    }
    
    6 - 이전 구성 삭제
  • 기존 현장 스토리지 구성 제거
  • $fieldStorage->delete();
    
  • 모든 필드 값 대량 지우기
  • field_purge_batch(N); // N is the batch number
    
    7 - 새 필드 구성에 데이터 삽입
  • 새로운 현장 스토리지 구성 생성
  • $newFieldStorage = FieldStorageConfig::create($newFieldStorage);
    $newFieldStorage->save();
    
  • 새 필드 구성 만들기
  • foreach ($newFieldsArray as $field) {
       $fieldConfig = FieldConfig::create($field);
       $fieldConfig->save();
    }
    
  • 새 필드에 데이터 삽입
  • // Row data
    if (!is_null($rows)) {
      foreach ($rows as $row) {
       $database->insert($table)->fields((array) $row)->execute();
      }
    }
    // Revision data
    if (!is_null($revision_rows)) {
      foreach ($revision_rows as $row) {
        $database->insert($revisionTable)->fields((array) $row)->execute();
      }
    }
    
    8 - 데이터베이스 업데이트 실행
    이 업데이트는 Drush 또는 Drupal CLI 명령을 사용하여 수행할 수 있습니다.참고: 데이터베이스를 백업합니다.
    // Drupal CLI
    bin/drupal upex
    // Drush CLI
    bin/drush updb
    
    전체 코드 세그먼트
    <?php
    
    use \Drupal\field\Entity\FieldConfig;
    use \Drupal\field\Entity\FieldStorageConfig;
    
    /**
     * Change field_number from Number (integer) to Text (formatted)
     */
    function field_migration_medium_update_9001() {
    
      $entityType = 'node';
      $oldFieldName = 'field_number';
      $table = $entityType . '__' . $oldFieldName;
      $revisionTable = $entityType . '_revision__' . $oldFieldName;
      $newFieldsArray = [];
    
      $database = \Drupal::database();
    
      $rows = NULL;
      $revisionRows = NULL;
      if ($database->schema()->tableExists($table)) {
        $rows = $database->select($table, 'n')->fields('n')->execute()
          ->fetchAll();
        $revisionRows = $database->select($revisionTable, 'n')->fields('n')->execute()
          ->fetchAll();
      }
    
      // Get field storage config.
      $fieldStorage = FieldStorageConfig::loadByName($entityType, $oldFieldName);
    
      // Check if field storage config exist.
      if (is_null($fieldStorage)) {
        return t('Field Storage does not exist');
      }
    
      $newFieldStorage = $fieldStorage->toArray();
      $newFieldStorage['type'] = 'text';
      $newFieldStorage['settings'] = array(
        'max_length' => 255
      );
    
      foreach ($fieldStorage->getBundles() as $bundle => $label) {
        $field = FieldConfig::loadByName($entityType, $bundle, $oldFieldName);
    
        $newField = $field->toArray();
        $newField['field_type'] = 'text';
        $newField['settings'] = array(
          'max_length' => 255
        );
        $newFieldsArray[] = $newField;
      }
    
      $fieldStorage->delete();
      field_purge_batch(40);
    
      // Create new field storage.
      $newFieldStorage = FieldStorageConfig::create($newFieldStorage);
      $newFieldStorage->save();
    
      // Create new fields.
      foreach ($newFieldsArray as $field) {
        $fieldConfig = FieldConfig::create($field);
        $fieldConfig->save();
      }
    
      // Restore existing data in new fields.
      if (!is_null($rows)) {
        foreach ($rows as $row) {
        $database->insert($table)
                 ->fields((array) $row)
                 ->execute();
        }
      }
    
      if (!is_null($revisionRows)) {
        foreach ($revisionRows as $row) {
          $database->insert($revisionTable)
                   ->fields((array) $row)
                   ->execute();
         }
      }
    }
    
    마지막 생각
    데이터베이스 업데이트가 실행되면 Drupal은 각 모듈의 업데이트 ID를 추적합니다.이것Load the name은 Drush를 사용하여 이루어집니다.주의:
    drush ev "drupal_set_installed_schema_version(module, version)"
    
    즐거운 코드:)

    좋은 웹페이지 즐겨찾기