ฉันสร้างโมดูลแบบกำหนดเองซึ่งสร้างประเภทฟิลด์แบบกำหนดเอง (พร้อมตัวจัดรูปแบบและวิดเจ็ต) และฉันต้องการทำให้คุณสมบัติหนึ่งของฟิลด์เพิ่มขึ้น (เพื่อเพิ่มค่าทีละหนึ่งสำหรับแต่ละอินสแตนซ์ของฟิลด์)
สิ่งที่ฉันมีคือ:
- web/modules/custom/asciinema/src/Plugin/Field/FieldType/AsciinemaItem.php (คำจำกัดความของฟิลด์)
สคีมาของฟังก์ชันสแตติกสาธารณะ (FieldStorageDefinitionInterface $field_definition) {
กลับ [
// คอลัมน์มีค่าที่ฟิลด์จะจัดเก็บ
'คอลัมน์' => [
// แสดงรายการค่าที่ฟิลด์จะบันทึก
'ความช่วยเหลือ' => [
'type' => 'อนุกรม',
'ขนาด' => 'ปกติ',
'description' => 'id ของอินสแตนซ์ asciinema',
'ไม่ได้ลงนาม' => จริง,
'ไม่เป็นโมฆะ' => จริง,
]
]
.....
'คีย์เฉพาะ' => [
'ช่วยเหลือ' => ['ช่วยเหลือ'],
]
];
// ฟังก์ชันนี้ช่วยให้แน่ใจว่าค่าจะเพิ่มขึ้นทุกครั้งที่มีการบันทึกอินสแตนซ์ของฟิลด์ใหม่
ฟังก์ชั่นสาธารณะ preSave () {
ถ้า ($this->getEntity()->isNew()) {
// เพิ่มมูลค่าของความช่วยเหลือเมื่อต้องจัดการกับเอนทิตีใหม่
$fieldConfig = $this->getFieldDefinition();
$field_name = $fieldConfig->getName();
$entity_type = $fieldConfig->getTargetEntityTypeId();
$query = \Drupal::database()->select($entity_type . '__' . $field_name, 'ef')
->fields('ef', [$field_name . '_' . 'ช่วยเหลือ'])
->orderBy($field_name . '_' . 'ช่วยเหลือ', 'DESC');
$lastIndex = $query->execute()->fetchField();
$result = !empty($lastIndex) ? $lastIndex + 1 : 1;
$this->values['aid'] = ผลลัพธ์ $;
$this->setValue($this->values);
}
}
- web/modules/custom/asciinema/src/Plugin/Field/FieldWidget/AsciinemaDefaultWidget.php (วิดเจ็ตฟิลด์)
ฟังก์ชั่นสาธารณะ formElement(
FieldItemListInterface $รายการ
$เดลต้า
อาร์เรย์ $องค์ประกอบ,
อาร์เรย์ &$ ฟอร์ม
FormStateInterface $form_state
) {
// ค่าปัจจุบันพร้อมทางเลือกสำรอง
$aid = isset($items[$delta]->aid) ? $items[$delta]->aid : 0;
....
$element['asciinema']['id']['aid'] = [
'#title' => t('เอดส์'),
'#description' => t('Asciinema ID.'),
'#disabled' => จริง,
'#type' => 'ช่องข้อความ',
'#default_value' => $ช่วยเหลือ,
];
....
ส่งคืนองค์ประกอบ $;
....
การนวดฟังก์ชั่นสาธารณะFormValues(
อาร์เรย์ $values,
อาร์เรย์ $form,
FormStateInterface $form_state
) {
foreach (ค่า $ เป็น & $ ค่า) {
//ไอดี.
$value['aid'] = $value['asciinema']['id']['aid'];
....
unset($value['asciinema']);
}
คืนค่า $;
}
- เว็บ/โมดูล/กำหนดเอง/asciinema/src/Plugin/Field/FieldFormatter/AsciinemaDefaultFormatter.php (ตัวจัดรูปแบบ):
ฟังก์ชั่นสาธารณะ viewElements (FieldItemListInterface $items, $langcode) {
$องค์ประกอบ = [];
$แหล่งที่มา = [];
foreach ($items เป็น $delta => $item) {
// แสดงผลโดยใช้ธีม asciinema_default
$แหล่งที่มา['asciinema'] = [
'#theme' => 'asciinema_default',
'#asciinema' => [
'aid' => $item->aid,
]
];
...
$องค์ประกอบ[$เดลต้า] = [
'#markup' => \Drupal::service('renderer')->render($source),
];
}
ส่งคืนองค์ประกอบ $;
ขณะนี้ฉันสามารถบันทึกค่าที่ป้อนในฟิลด์ที่กำหนดเองและ ความช่วยเหลือ
ได้รับเพิ่มขึ้นสำหรับแต่ละอินสแตนซ์ของฟิลด์ อย่างไรก็ตาม ฉันไม่สามารถแก้ไขข้อมูลที่ผ่านมาได้ เพราะนั่นจะทำให้เกิด:
ข้อสังเกต: ข้อความ PHP: Uncaught ข้อยกเว้นของ PHP Drupal\Core\Entity\EntityStorageException: "SQLSTATE[23505]: การละเมิดเฉพาะ: 7 ข้อผิดพลาด: ค่าคีย์ที่ซ้ำกันละเมิดข้อจำกัดเฉพาะ "node_revision__asciinema__asciinema_aid__key"
php_1 | รายละเอียด: คีย์ (asciinema_aid)=(4) มีอยู่แล้ว:
ฉันชอบที่จะค้นหาว่ามีอะไรขาดหายไปหรือหาวิธีที่ดีกว่าและสะอาดกว่าในการจัดการกับฟิลด์ที่เพิ่มขึ้น
แก้ไข:
ฉันสามารถหลีกเลี่ยงข้อ จำกัด ได้โดยการลบ:
'คีย์เฉพาะ' => [
'ช่วยเหลือ' => ['ช่วยเหลือ'],
]
... จากคำจำกัดความของ schema และเพิ่มเงื่อนไขพิเศษในฟังก์ชัน presave()
ฟังก์ชั่นสาธารณะ preSave () {
ถ้า ($this->getEntity()->isNew() || ว่าง($this->values['aid'])) {
...
}
อย่างไรก็ตาม ฉันไม่คิดว่านี่เป็นคำตอบที่ชัดเจน แต่เป็นวิธีแก้ปัญหามากกว่าฉันต้องการใช้ประโยชน์จากข้อ จำกัด ของฐานข้อมูลเช่นการเพิ่มอัตโนมัติหรือคีย์ที่ไม่ซ้ำเช่นกัน จนถึงวันนี้ฉันยังไม่พบวิธีการทำงานกับคุณสมบัติฟิลด์ที่กำหนดเอง