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:
- 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);
}
}
- 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;
}
- 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.