Puncte:0

Cum pot seta o proprietate incrementală pe un câmp personalizat?

drapel jp

Am construit un modul personalizat care creează un tip de câmp personalizat (cu formatator și widget) și aș dori să fac o proprietate a câmpului incrementală (pentru a-i crește valoarea cu câte una pentru fiecare instanță a câmpului.)

Ce am pana acum este:

  1. web/modules/custom/asciinema/src/Plugin/Field/FieldType/AsciinemaItem.php (definiția câmpului)
  schema funcției statice publice (FieldStorageDefinitionInterface $field_definition) {
    întoarcere [
      // coloanele conține valorile pe care câmpul le va stoca
      'coloane' => [
        // Listează valorile pe care câmpul le va salva.
        'ajutor' => [
          'type' => 'serial',
          'size' => 'normal',
          'description' => 'Idul instanței asciinema.',
          'unsigned' => TRUE,
          „nu nul” => ADEVĂRAT,
        ],
      ],
      .....
      'chei unice' => [
        'aid' => ['aid'],
      ],
    ];

  // Această funcție asigură că valoarea este incrementată de fiecare dată când este salvată o nouă instanță de câmp.
  funcția publică preSave() {
    if ($this->getEntity()->isNew()) {
      // Creșteți valoarea ajutorului atunci când aveți de-a face cu o nouă entitate.
      $fieldConfig = $this->getFieldDefinition();
      $field_name = $fieldConfig->getName();
      $entity_type = $fieldConfig->getTargetEntityTypeId();
      
      $interogare = \Drupal::database()->select($entity_type . '__' . $field_name, 'ef')
                ->fields('ef', [$field_name . '_' . 'aid'])
                ->orderBy($field_name . '_' . 'aid', 'DESC');
      $lastIndex = $query->execute()->fetchField();
      
      $rezultat = !empty($lastIndex) ? $lastIndex + 1 : 1;

      $this->values['aid'] = $rezultat;
      $this->setValue($this->values);
    }
  }
  1. web/modules/custom/asciinema/src/Plugin/Field/FieldWidget/AsciinemaDefaultWidget.php (widgetul câmpului).
 funcția publică formElement(
    FieldItemListInterface $items,
    $delta,
    matrice $element,
    matrice &$form,
    FormStateInterface $form_state
  ) {
    // Valori curente cu alternative.
    $aid = isset($items[$delta]->aid) ? $articole[$delta]->aid : 0;
    ....
    $element['asciinema']['id']['aid'] = [
      '#title' => t('AJUTOR'),
      '#description' => t('Asciinema ID.'),
      '#disabled' => TRUE,
      '#type' => 'câmp text',
      '#default_value' => $aid,
    ];
    ....
    returnează $element;

    ....

  funcția publică massageFormValues(
    matrice $valori,
    matrice $form,
    FormStateInterface $form_state
  ) {
    foreach ($value ca &$valoare) {
      // ID.
      $value['aid'] = $value['asciinema']['id']['aid'];
    ....
      unset($value['asciinema']);
    }

    returnează $valori;
  }
  1. web/modules/custom/asciinema/src/Plugin/Field/FieldFormatter/AsciinemaDefaultFormatter.php (formatatorul):
  funcția publică viewElements(FieldItemListInterface $items, $langcode) {
    $elemente = [];
    $sursa = [];

    foreach ($items ca $delta => $item) {
      // Redați ieșirea folosind tema asciinema_default.
      $source['asciinema'] = [
        '#theme' => 'asciinema_default',
        '#asciinema' => [
          'aid' => $item->aid,
        ],
      ];
      ...
      $elemente[$delta] = [
        '#markup' => \Drupal::service('renderer')->render($sursa),
      ];
    }

    returnează $elemente;

Așa cum este acum, pot salva valorile introduse în câmpul meu personalizat și ajutor crește pentru fiecare instanță de câmp. Cu toate acestea, nu pot edita niciuna dintre datele anterioare, deoarece ar genera:

ANUNȚ: Mesaj PHP: Excepție PHP neprinsă Drupal\Core\Entity\EntityStorageException: „SQLSTATE[23505]: Încălcare unică: 7 EROARE: valoarea cheii duplicate încalcă constrângerea unică „node_revision__asciinema__asciinema_aid__key”
php_1 | DETALII: Cheia (asciinema_aid)=(4) există deja.:

Mi-ar plăcea să aflu ce lipsește sau să găsesc o modalitate mai bună și mai curată de a face față câmpurilor incrementale.

EDITAȚI | ×:

Am reușit să ocol limitările eliminând:

'chei unice' => [
        'aid' => ['aid'],
      ],

... din definițiile schemei și adăugarea unei condiții suplimentare în funcția presave().

funcția publică preSave() {
    if ($this->getEntity()->isNew() || empty($this->values['aid'])) {
      ...
    }

Cu toate acestea, nu consider că acesta este un răspuns definitiv, ci mai degrabă o soluție.Aș dori să folosesc și constrângerile bazei de date, cum ar fi AUTO INCREMENT sau UNIQUE KEY. Până în prezent, nu am aflat cum să funcționeze cu proprietăți de câmp personalizate.

Jaypan avatar
drapel de
Poate doriți să includeți care este obiectivul dvs. general, deoarece este foarte posibil să existe o modalitate mai Drupal de a face ceea ce încercați să faceți, care nu va implica nimic din ceea ce ați arătat.
dasj19 avatar
drapel jp
@Jaypan Ei bine, obiectivul meu final este să am un câmp care să ofere informații pentru a afișa un jucător asciinema: https://asciinema.org/ . Am creat un câmp personalizat cu proprietăți pentru fiecare parte a datelor necesare pentru a afișa playerul. Acum am nevoie de un ID unic pentru fiecare instanță de câmp pentru a putea avea mai mulți jucători pe aceeași pagină și a nu intra în conflict între ei.
drapel cn
De ce să nu folosiți ID-ul entității? Sau dacă un câmp cu mai multe valori, o combinație de ID-ul entității și delta câmpului?

Postează un răspuns

Majoritatea oamenilor nu înțeleg că a pune multe întrebări deblochează învățarea și îmbunătățește legătura interpersonală. În studiile lui Alison, de exemplu, deși oamenii își puteau aminti cu exactitate câte întrebări au fost puse în conversațiile lor, ei nu au intuit legătura dintre întrebări și apreciere. În patru studii, în care participanții au fost implicați în conversații ei înșiși sau au citit transcrieri ale conversațiilor altora, oamenii au avut tendința să nu realizeze că întrebarea ar influența – sau ar fi influențat – nivelul de prietenie dintre conversatori.