Score:2

เพิ่มฟิลด์ให้กับผู้ใช้ใน hook_update_n

ธง pl

รุ่นล่าสุดของโมดูลที่มีอยู่ของเราจำเป็นต้องกำหนดฟิลด์ใหม่จำนวนมากที่แนบกับผู้ใช้ drupal สำหรับแต่ละฟิลด์ ใน {module}/config/optional จะมีฟิลด์ config และฟิลด์ storage config จากนั้นฉันใช้ hook_update_n ใน {module}/{module}.install เพื่อตรวจหารายการกำหนดค่าใหม่ และเพิ่มเข้าไปหากไม่มีอยู่ การรันโค้ดจะติดตั้งการกำหนดค่า (ฉันสามารถเห็นได้ด้วย drush cget) แต่ไม่ได้สร้างตาราง DB ที่สอดคล้องกันสำหรับฟิลด์ใหม่

ถ้าฉันไปที่หน้าส่วนใหญ่เช่น /admin/config/people/accounts/fieldsฉันได้รับ "เว็บไซต์พบข้อผิดพลาดที่ไม่คาดคิด โปรดลองอีกครั้งในภายหลัง"

ถ้าฉันล้างแคช (ดรัช cr) ฉันได้รับข้อผิดพลาดที่ระบุว่า

ใน ExceptionHandler.php บรรทัดที่ 53:

  SQLSTATE[42S02]: ไม่พบตารางฐานหรือมุมมอง: 1146 ไม่มีตาราง 'intranet.user__field_s_uid': SELECT "t".*
  จาก
  "ผู้ใช้__field_s_uid" "t"
  WHERE ("entity_id" IN (:db_condition_placeholder_0)) และ ("deleted" = :db_condition_placeholder_1) และ ("langcode" IN (:db_condition_placeholder_2, :db_c
  ondition_placeholder_3, :db_condition_placeholder_4))
  สั่งซื้อโดย "เดลต้า" ASC; อาร์เรย์
  (
      [:db_condition_placeholder_0] => 0
      [:db_condition_placeholder_1] => 0
      [:db_condition_placeholder_2] => th
      [:db_condition_placeholder_3] => และ
      [:db_condition_placeholder_4] => zxx
  )

ใน StatementWrapper.php บรรทัดที่ 116:

  SQLSTATE[42S02]: ไม่พบตารางฐานหรือมุมมอง: 1146 ไม่มีตาราง 'intranet.user__field_s_uid'

เพื่อให้ไซต์ทำงานได้อีกครั้ง ฉันต้องลบการกำหนดค่า (drush cdel...)

ฉันพลาดอะไรไปที่ทำให้ไม่สามารถสร้างที่เก็บข้อมูล db ได้ ฉันจำเป็นต้องสร้างตาราง db โดยทางโปรแกรมเพื่อให้ฟิลด์ใช้หรือไม่ (ถ้าเป็นเช่นนั้นได้อย่างไร)

ไฟล์: {module}.install

<?php                                                              
ใช้ Drupal\Component\Serialization\Yaml;                           
ใช้ Drupal\Component\Utility\NestedArray;                          
ใช้ Drupal\field\Entity\FieldStorageConfig;                        
ใช้ Drupal\field\Entity\FieldConfig;                               
                                                                   
ฟังก์ชัน {โมดูล}_update_9001(&$sandbox = NULL){             
  $modulePath = \Drupal::service('extension.list.module')          
        ->getPath('{โมดูล}');                      
  $config_factory = \Drupal::configFactory();                      
  $configPathObjects = \Drupal::service('file_system')             
    ->scanDirectory($modulePath.'/config/ทางเลือก','~field.*~');   
                                                                   
  foreach ($configPathObjects เป็น $configPath){                     
                                                                   
    $config = $config_factory->getEditable($configPath->ชื่อ);     
    ถ้า($config->isNew()){                                          
      $configSettings = NestedArray::mergeDeep(                    
          Yaml::ถอดรหัส(                                            
            file_get_contents(                                     
              "$modulePath/config/ทางเลือก/{$configPath->ชื่อไฟล์}"
              )                                                    
            ),$การกำหนดค่า                                              
          );                                                       
      $config->setdata($configSettings);                           
      $config->save(จริง);                                         
    }                                                              
  }                                                                
}                                                                  

ไฟล์: config/ทางเลือก/field.field.user.user.field_s_uid.yml

รหัสภาษา: th                                                                   
สถานะ: จริง                                                                   
การพึ่งพา:                                                                  
  การกำหนดค่า:                                                                      
    - field.storage.user.field_s_uid                                           
  โมดูล:                                                                      
    - ผู้ใช้                                                                     
รหัส: user.user.field_s_uid                                                      
field_name: field_s_uid                                                        
entity_type: ผู้ใช้                                                              
กลุ่ม: ผู้ใช้                                                                   
ป้ายกำกับ: s_uid                                                                   
คำอธิบาย: 'ID เฉพาะสำหรับผู้ใช้นี้ ซึ่งตั้งค่าโดยอัตโนมัติโดย DB ไม่ควรแก้ไขโดยผู้ใช้/ผู้ดูแลระบบ'                                              
จำเป็น: เท็จ                                                                
แปลได้: เท็จ                                                            
default_value: { }                                                            
default_value_callback: ''                                                     
การตั้งค่า:                                                                      
  นาที: เป็นโมฆะ                                                                    
  สูงสุด: null                                                                    
  คำนำหน้า: ''                                                                   
  คำต่อท้าย: ''                                                                   
field_type: จำนวนเต็ม                                                            

ไฟล์: config/ทางเลือก/field.storage.user.field_s_uid.yml

รหัสภาษา: th
สถานะ: จริง
การพึ่งพา:
  โมดูล:
    - ผู้ใช้
รหัส: user.field_s_uid
field_name: field_s_uid
entity_type: ผู้ใช้
ประเภท: จำนวนเต็ม
การตั้งค่า:
  ไม่ได้ลงนาม: เท็จ
  ขนาด: ปกติ
โมดูล: แกน
ล็อค: เท็จ
จำนวนสมาชิก: 1
แปลได้: จริง
ดัชนี: { }
Persis_with_no_fields: เท็จ
custom_storage: เท็จ
ru flag
คุณต้องแน่ใจว่าได้ติดตั้ง FieldStorage ก่อน
Score:2
ธง pl

โซลูชันสุดท้ายตามโซลูชันที่ยอมรับจาก @ 4k4 (ดูคำตอบ).

<?php
ใช้ Drupal\Core\Database\Database;
ใช้ Drupal\Component\Serialization\Yaml;
ใช้ Drupal\Component\Utility\NestedArray;
ใช้ Drupal\field\Entity\FieldStorageConfig;
ใช้ Drupal\field\Entity\FieldConfig;
ใช้ Drupal\Core\Utility\UpdateException;

/**
 * เพิ่มฟิลด์ที่จำเป็นให้กับเอนทิตีผู้ใช้
 */
ฟังก์ชัน {โมดูล}_update_9001(){
  $modulePath = \Drupal::service('extension.list.module')
        ->getPath('{โมดูล}');
  $configPathStorageObjects = \Drupal::service('file_system')
    ->scanDirectory($modulePath.'/config/optional','~field\.storage\.user\..*~');
  \Drupal::logger('staffdb')->notice('storage object: <pre>'.print_r($configPathStorageObjects,true).'</pre>');

  // เพิ่มที่เก็บข้อมูลฟิลด์ที่ขาดหายไป
  foreach ($configPathStorageObjects เป็น $configPath){
    $config = FieldStorageConfig::loadByName('user',str_replace('field.storage.user.','',$configPath->name));
    ถ้า(is_null($config)){
      $configSettings = Yaml::decode(
          file_get_contents(
            "$modulePath/config/ทางเลือก/{$configPath->ชื่อไฟล์}"
            )
          );
      $fieldStorage = FieldStorageConfig::create($configSettings);
      $fieldStorage->save();
    }
  }

  // เพิ่มฟิลด์ที่ขาดหายไปให้กับผู้ใช้
  $configPathFieldObjects = \Drupal::service('file_system')
    ->scanDirectory($modulePath.'/config/optional','~field\.field\.user\.user\..*~');
  foreach ($configPathFieldObjects เป็น $configPath){
    $config = FieldConfig::loadByName('user', 'user', str_replace('field.field.user.user.','',$configPath->name));
    ถ้า(is_null($config)){
      $configSettings = Yaml::decode(
          file_get_contents(
            "$modulePath/config/ทางเลือก/{$configPath->ชื่อไฟล์}"
            )
          );
      $field = FieldConfig::create($configSettings);
      $field->save();
    }
  }
}
Score:2
ธง cn

คุณต้องมีคลาสเอนทิตีการกำหนดค่า FieldStorageConfig::create() และ FieldConfig::create() คุณมีคำสั่งการใช้งานแล้วและไม่ได้ใช้ มิฉะนั้น เหตุการณ์เอนทิตีเช่น postcreate และ presave จะไม่ถูกเรียกใช้

BTW หากคุณแก้ไขการกำหนดค่าของเอนทิตีการกำหนดค่าผ่าน $config_factory->getEditable() สิ่งนี้ใช้ได้ตราบเท่าที่คุณไม่ได้แก้ไขสิ่งใดที่ส่งผลกระทบต่อเหตุการณ์เอนทิตีที่กล่าวถึงหากคุณต้องการบันทึกเอนทิตีการกำหนดค่าแทนที่ฟรี ให้โหลดแทนด้วย ConfigEntityStorageInterface::loadOverrideFree().

ru flag
การใช้ `FieldStorageConfig` หรือ `FieldConfig` หมายความว่าคุณต้องตรวจสอบการกำหนดค่า (-type) แต่ละรายการอย่างชัดเจนทีละรายการ ไม่มีความเป็นไปได้ที่จะติดตั้งไดเร็กทอรีทั้งหมดของไฟล์ปรับแต่งโดยพลการในคราวเดียว? ฉันใช้วิธีที่คล้ายกันกับ @Kevin Finkenbinder ซึ่งฉันเห็นใน [ไฟล์ติดตั้งการแจกจ่าย Varbase](https://git.drupalcode.org/project/varbase_bootstrap_paragraphs/-/blob/9.0.x/varbase_bootstrap_paragraphs ติดตั้ง#L39): FieldStorage ก่อน แล้วค่อยอย่างอื่น แนวทางนี้ไม่รอดหรือ?
4uk4 avatar
cn flag
รหัสที่เชื่อมโยงใช้งานได้เนื่องจาก $config_installer->installOptionalConfig() ซึ่งจะบันทึกเอนทิตีการกำหนดค่าที่เพิ่มเข้าไปใหม่ในภายหลัง
4uk4 avatar
cn flag
และในตอนท้ายโค้ดกำลังใช้เคล็ดลับเพื่อแก้ไขข้อผิดพลาดในการอัปเดต https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Entity%21EntityDefinitionUpdateManager.php/function/EntityDefinitionUpdateManager%3A%3AapplyUpdates /8.9.x. วิธีนี้ใช้ไม่ได้แล้ว
pl flag
ขอขอบคุณ. สิ่งนี้ให้สิ่งที่ฉันต้องการและทำเครื่องหมายว่าเป็นคำตอบที่ยอมรับ เพื่อช่วยเหลือผู้อื่น เช่น @Hudri ฉันยังโพสต์ด้วยรหัสสุดท้ายด้านล่าง (https://drupal.stackexchange.com/a/307977/19071) ที่อนุญาตให้ฉันทำซ้ำผ่านไฟล์หลายไฟล์ที่เพิ่มเข้ามา

โพสต์คำตอบ

คนส่วนใหญ่ไม่เข้าใจว่าการถามคำถามมากมายจะปลดล็อกการเรียนรู้และปรับปรุงความสัมพันธ์ระหว่างบุคคล ตัวอย่างเช่น ในการศึกษาของ Alison แม้ว่าผู้คนจะจำได้อย่างแม่นยำว่ามีคำถามกี่ข้อที่ถูกถามในการสนทนา แต่พวกเขาไม่เข้าใจความเชื่อมโยงระหว่างคำถามและความชอบ จากการศึกษาทั้ง 4 เรื่องที่ผู้เข้าร่วมมีส่วนร่วมในการสนทนาด้วยตนเองหรืออ่านบันทึกการสนทนาของผู้อื่น ผู้คนมักไม่ตระหนักว่าการถามคำถามจะมีอิทธิพลหรือมีอิทธิพลต่อระดับมิตรภาพระหว่างผู้สนทนา