Puncte:4

Cum se face ca numele termenilor de taxonomie să fie unice pentru fiecare utilizator?

drapel cn

Am un vocabular de taxonomie, Grupuri.

Cerințe

  • Utilizatori diferiți pot crea grupuri cu același nume. (Utilizatorul A poate realiza un merele grup, iar utilizatorul B poate face și un merele grup.)
  • Același utilizator nu poate face două grupuri cu același nume (Utilizatorul A nu poate face două merele grupuri.)

Cum pot implementa asta?

D8/9 oferă o constrângere de câmp după cum este explicat în acest răspuns și această postare pe blog, dar acest lucru face un câmp unic pentru toți utilizatorii.

Vreau să fac nume de termen de taxonomie unic per utilizator. De asemenea, trebuie să funcționeze cu JSON:API. Cum pot face acest lucru?

Puncte:4
drapel cn

Aveți voie să adăugați un constrângeri de validare personalizate folosind acești pași:

  1. Pasul 1: Definiți constrângerea:

    Definiția constrângerii va merge în spațiul de nume Drupal[MODULENAME]\Plugin\Validation\Constraint și va extinde Symfony\Component\Validator\Constraint. În această clasă sunt definite tipurile de încălcări ale constrângerii, împreună cu mesajele de eroare care vor fi afișate pentru încălcările date.

  2. Pasul 2: Creați validarea pentru constrângere

    Următorul pas este crearea clasei care va valida constrângerea. Validarea constrângerii va merge în spațiul de nume Drupal[MODULENAME]\Plugin\Validation\Constraint și va extinde Symfony\Component\Validator\ConstraintValidator. În această clasă, valorile transmise vor fi returnate, iar eventualele încălcări vor fi înregistrate.

    Vă rugăm să rețineți că numele clasei dvs. de validare este de așteptat să fie ${ConstraintClassName}Validator în mod implicit. Dacă doriți să utilizați un nume diferit, puteți suprascrie metoda validatedBy() a clasei dvs. Constraint, pe care ați creat-o la pasul 1.

iar pentru pasul final puteți adăuga noua constrângere în câmpul dvs. la fel ca și raspunsul pe care l-ai mentionat

Acum având aceste informații, puteți adăuga un câmp de referință pentru utilizator la taxonomia dvs., astfel încât fiecare termen va conține informații despre autor, puteți utiliza hook_Entity_Type_presave pentru a seta acest câmp în mod programatic

apoi puteți crea o constrângere personalizată numită notUniquePerArthor (sau orice nume doriți), apoi, în pasul 2, unde definiți metoda isUniquePerUser, puteți rula o interogare și puteți obține o listă de termeni de taxonomie care au eticheta egală cu valoarea și autorul egal cu utilizatorul curent, dacă această interogare returnează o valoare, atunci aceasta înseamnă că acest termen nu este unic (utilizatorul a definit acest termen înainte) și puteți genera o eroare

drapel cn
Minunat! Aceasta pare o modalitate excelentă de a face acest lucru, cu excepția faptului că numele termenului nu este un câmp, nu? Este ca și titlul nodului/paginii -- nu este accesibil (din câte știu eu) ca câmp. Deci, ce fac în acest caz?
apaderno avatar
drapel us
@PatrickKenny Titlul nodului este un câmp de entitate: `$fields['title'] = BaseFieldDefinition::create('string')->setLabel(t('Title'))->setRequired(TRUE)->setTranslatable(TRUE) )->setRevisionable(TRUE)->setSetting('max_length', 255)->setDisplayOptions('view', ['label' => 'hidden','type' => 'string','weight' => - 5,]);` Nu vă confundați cu Drupal care arată titlul paginii într-un bloc.
apaderno avatar
drapel us
Același lucru este valabil și pentru numele termenului de taxonomie: `$fields['name'] = BaseFieldDefinition::create('string')->setLabel(t('Name'))->setTranslatable(TRUE)->setRevisionable(TRUE) )->setRequired(TRUE)->setSetting('max_length', 255)->setDisplayOptions('view', ['label' => 'hidden','type' => 'string','weight' => - 5,]);`
drapel cn
@apaderno Mulțumesc, este foarte util. Din păcate, în `hook_entity_bundle_field_info_alter()`, se pare că câmpul `name` nu este disponibil, ceea ce m-a derutat. Întrebare ulterioară aici: https://drupal.stackexchange.com/questions/305789/how-to-set-a-validation-constraint-for-the-taxonomy-term-name
apaderno avatar
drapel us
@PatrickKenny Asta pentru că `hook_entity_bundle_field_info_alter()` este pentru câmpurile pachetului, în timp ce numele taxonomiei este un câmp de bază, ceea ce înseamnă că este prezent în fiecare pachet de taxonomie.
Alireza Tabatabaeian avatar
drapel cn
@PatrickKenny, puteți folosi `hook_entity_base_field_info_alter` https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Entity%21entity.api.php/function/hook_entity_base_field_info_alter/8. definiții precum id sau titlu sau...
Puncte:3
drapel cn

Mulțumim lui @Alireza Tabatabaeian pentru asta. Pur și simplu postez codul pe care l-am folosit pe baza acelui răspuns.

La taxonomia căreia am vrut să aplic constrângerea, am adăugat a field_term_ref_author referire la entitate la utilizator.

mymodule.php

funcția MYMOUDLE_taxonomy_term_presave(TermInterface $term) {
  $vocabular = $term->bundle();
  comutator ($vocabular) {
    caz „my_vocab_type”:
      dacă ($term->isNew()) {
        // Setați autorul (prin câmpul personalizat).
        $current_user = \Drupal::currentUser()->id();
        $term->set('field_term_ref_author', $current_user);
      }
    pauză;

funcția MYMODULE_entity_base_field_info_alter(&$fields, $entity_type) {
  if ($entity_type->id() === 'termen_taxonomie') {
    if (isset($fields['nume'])) {
      $fields['nume']->addConstraint('TermNameUniquePerUser');
    }
  }
}

mymodule/src/Plugin/Validation/Constraint/TermNameUniquePerUser.php

<?php

spațiu de nume Drupal\MYMODULE\Plugin\Validation\Constraint;

utilizați Symfony\Component\Validator\Constraint;

/**
 * Verifică dacă valoarea trimisă este unică pentru utilizator.
 *
 * @Constraint(
 * id = "TermNameUniquePerUser",
 * label = @Translation ("Nume termen unic per utilizator", context = "Validare"),
 * tip = „șir”
 * )
 */
clasa TermNameUniquePerUser extinde Constraint {
  // Mesajul care va fi afișat dacă valoarea nu este unică.
  public $notUnique = 'Ați creat deja un termen numit %value.';

}

mymodule/src/Plugin/Validation/Constraint/TermNameUniquePerUserValidator.php

<?php

spațiu de nume Drupal\MYMODULE\Plugin\Validation\Constraint;

utilizați Symfony\Component\Validator\Constraint;
utilizați Symfony\Component\Validator\ConstraintValidator;

/**
 * Validează constrângerea TermNameUniquePerUser.
 */
clasa TermNameUniquePerUserValidator extinde ConstraintValidator {

  /**
   * {@inheritdoc}
   */
  validare funcție publică($articole, Constrângere $constrângere) {
    foreach ($articole ca $item) {
      // Apoi verificați dacă valoarea este unică.
      dacă (!$acest->este Unic($articol->valoare)) {
        $this->context->addViolation($constraint->notUnique, ['%value' => $item->value]);
      }
    }
  }

  /**
   * Este unic?
   *
   * @param șir $valoare
   */
  funcția privată esteUnică($valoare) {
    $uid = \Drupal::currentUser()->id();
    $term_name_query = \Drupal::entityQuery('taxonomy_term')
      ->condition('nume', $valoare, '=')
      ->condition('field_term_ref_author', $uid);
    // Dacă interogarea are rezultate, atunci nu este unică.
    // Așa că ar trebui să returnăm opusul dacă există rezultate.
    return !($term_name_query->execute());
  }

}

Lucrul bun despre scrierea interogării de entitate în acest fel este că, dacă vocabularul de taxonomie nu are a field_term_ref_author câmp, nu vor exista niciodată rezultate, așa că constrângerea se va evalua corect cu termeni care sunt în pachete care nu sunt supuși constrângerii (deși acest lucru va duce la o interogare irosită a bazei de date.)

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.