Jak dodać niestandardową procedurę sprawdzania poprawności do istniejącego formularza / pola?


21

Jak dodać niestandardową procedurę sprawdzania poprawności do istniejącego formularza (lub pola formularza) w Drupal 8?

Mam formularz, którego nie utworzyłem. Chcę dodać własne reguły sprawdzania poprawności w niektórych polach po przesłaniu formularza.

W przypadku Drupal 7 niestandardowe sprawdzenie poprawności formularza? wyjaśnia, jak zaimplementować, hook_form_alter()a następnie dodać moduł obsługi sprawdzania poprawności] [1] do $form['#validate']tablicy, ale w formularzach Drupal 8 są klasy. Sprawdzanie poprawności odbywa się za pomocą validateForm()metody i nie wiem, jak podłączyć do tego mój kod.



1
To nie jest dokładnie duplikat. Moje pytanie dotyczy D8, twój link dotyczy D7.
— AngularChef

Zetknąłem się z tym dzisiaj i chciałem tylko zwrócić uwagę na inne osoby, jeśli nie korzystasz z POST (chciałem przesłać adres URL do istniejącej strony widoku) ani z funkcją validateForm, ani z submForm. Z perspektywy czasu jest to oczywiste .... ale spędziłem 30 minut, próbując to
— rozgryźć

Odpowiedzi:


19

#validateNieruchomość jest nadal używany w Drupal 8. (Z roztworu ADI można zastąpić istniejący walidator)

Jeśli chcesz dodać niestandardowy walidator oprócz domyślnego, musisz dodać coś takiego w hook_form_FORM_ID_alter (lub podobnym):

$form['#validate'][] = 'my_test_validate';

Dzięki Shabir. Tak więc dodanie niestandardowego walidatora działa tak samo w D7 i D8. ;)
— AngularChef,

Dokładnie sprawdź kod modułu węzła. istnieje wiele przykładów
— Shabir A.

2
Właśnie próbowałem i działało idealnie, dziękuję. Należy pamiętać, że w przeciwieństwie do tego, co mówi Dokumentacja interfejsu API formularza D8 dla #validate(twój link), nie należy używać go $form_statejako tablicy (sposób D7), ale jako obiekt implementujący FormStateInterface(sposób D8). Innymi słowy, kod w niestandardowym walidatorze powinien być analogiczny do kodu, który można znaleźć w oryginalnej validateForm()metodzie.
— AngularChef,

25

Berdir podał poprawną odpowiedź, że ograniczenie jest właściwą drogą do dodania sprawdzania poprawności do pola w Drupal 8. Oto przykład.

W poniższym przykładzie będę pracował z węzłem typu podcast, który ma pole pojedynczej wartości field_podcast_duration. Wartość tego pola musi być sformatowana jako GG: MM: SS (godziny, minuty i sekundy).

Aby utworzyć ograniczenie, należy dodać dwie klasy. Pierwszy to definicja ograniczenia, a drugi to walidator ograniczenia. Oba są wtyczkami w przestrzeni nazw Drupal\[MODULENAME]\Plugin\Validation\Constraint.

Po pierwsze, definicja ograniczenia. Zauważ, że identyfikator wtyczki jest podany jako „PodcastDuration” w adnotacji (komentarzu) klasy. Zostanie to wykorzystane w dalszej części.

namespace Drupal\[MODULENAME]\Plugin\Validation\Constraint;

use Symfony\Component\Validator\Constraint;

/**
 * Checks that the submitted duration is of the format HH:MM:SS
 *
 * @Constraint(
 *   id = "PodcastDuration",
 *   label = @Translation("Podcast Duration", context = "Validation"),
 * )
 */
class PodcastDurationConstraint extends Constraint {

  // The message that will be shown if the format is incorrect.
  public $incorrectDurationFormat = 'The duration must be in the format HH:MM:SS or HHH:MM:SS. You provided %duration';
}

Następnie musimy podać moduł sprawdzania poprawności ograniczeń. Ta nazwa tej klasy będzie nazwą klasy z góry, z Validatordołączonym do niej:

namespace Drupal\[MODULENAME]\Plugin\Validation\Constraint;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

/**
 * Validates the PodcastDuration constraint.
 */
class PodcastDurationConstraintValidator extends ConstraintValidator {

  /**
   * {@inheritdoc}
   */
  public function validate($items, Constraint $constraint) {
    // This is a single-item field so we only need to
    // validate the first item
    $item = $items->first();

    // If there is no value we don't need to validate anything
    if (!isset($item)) {
      return NULL;
    }

    // Check that the value is in the format HH:MM:SS
    if (!preg_match('/^[0-9]{1,2}:[0-5]{1}[0-9]{1}:[0-5]{1}[0-9]{1}$/', $item->value)) {
      // The value is an incorrect format, so we set a 'violation'
      // aka error. The key we use for the constraint is the key
      // we set in the constraint, in this case $incorrectDurationFormat.
      $this->context->addViolation($constraint->incorrectDurationFormat, ['%duration' => $item->value]);
    }
  }
}

Wreszcie, musimy powiedzieć Drupal do korzystania z naszego ograniczenia w field_podcast_durationsprawie podcastrodzaju węzła. Robimy to w hook_entity_bundle_field_info_alter():

use Drupal\Core\Entity\EntityTypeInterface;

function HOOK_entity_bundle_field_info_alter(&$fields, EntityTypeInterface $entity_type, $bundle) {
  if (!empty($fields['field_podcast_duration'])) {
    $fields['field_podcast_duration']->addConstraint('PodcastDuration');
  }
}

Jeśli w końcu potrzebujesz innych wartości pól do sprawdzenia poprawności pola, możesz dodać ograniczenie do typu zawartości. Zobacz ten post na blogu: lakshminp.com/entity-validation-drupal-8-part-2
— ummdorian,

1
Interfejs API walidacji D8 został szczegółowo wyjaśniony na Drupal.org tutaj. Zapewnienie niestandardowego ograniczenia sprawdzania poprawności
— Sukhjinder Singh

1
Ponieważ pytanie dotyczy konkretnie interfejsu API formularza, a nie interfejsu API pola, w jaki sposób można dołączyć to ograniczenie do elementu formularza (a nie pola encji)?
— aaronbauman

Elementy formularza nie mogą mieć ograniczeń. Możesz dodać sprawdzanie poprawności do określonego elementu formularza za pomocą #element_validate. Zobacz najwyższą odpowiedź w tym wątku - działa tak samo w D8, jak w D7 drupal.stackexchange.com/questions/86990/...
— Jaypan

Upewnij się, że $item = $items->first();zaznaczyłeś i zwróciłeś NULL, jeśli nic tam nie ma, inaczej wystąpi błąd krytyczny podczas edycji pola: TypeError: Argument 2 przekazany do Drupal \ Component \ Utility \ NestedArray :: getValue () musi być tablicy typów, podana null, wywołana w /data/app/core/lib/Drupal/Core/Field/WidgetBase.php w linii 407 w Drupal \ Component \ Utility \ NestedArray :: getValue () (linia 69 rdzenia / lib / Drupal / Component /Utility/NestedArray.php).
— Ivan Zugec

16

Prawidłowym sposobem na to dla jednostki treści takiej jak węzeł jest zarejestrowanie jej jako ograniczenia.

Widzisz forum_entity_bundle_field_info_alter()i odpowiadające? ForumLeafograniczenie sprawdzania poprawności (należy pamiętać, że potrzebne są dwie klasy).

Na początku jest to nieco bardziej skomplikowane, ale zaletą jest to, że jest zintegrowane z interfejsem API do sprawdzania poprawności, dzięki czemu sprawdzanie poprawności nie ogranicza się do systemu formularzy, ale może na przykład także współpracować z węzłami przesłanymi za pośrednictwem interfejsu API REST.


Dobra uwaga: jest to coś nowego dla osób, które pisały kod dla Drupala 7. Jestem pewien, że istnieje wielu użytkowników, którzy spróbują dodać procedury sprawdzania poprawności, gdy ograniczenie będzie bardziej odpowiednie.
— kiamlaluno

Berdir: Badałem tę opcję, próbując ją wdrożyć hook_entity_bundle_field_info_alter()(jak opisano tutaj ), ale nigdy nie działała ... Wygląda na to, że istnieje udokumentowany problem z tym hakiem: drupal.org/node/2346347 .
— AngularChef,

Istnieją pewne problemy, ale nie sądzę, że są one związane z twoim problemem. forum.module pokazuje, że to działa. Udostępnij swój kod, w przeciwnym razie nie będzie możliwe wskazanie możliwych problemów w implementacji.
— Berdir,

1
Chciałbym skorzystać z tej metody, ale dopóki nie będzie dobrego przykładu jej użycia z typami danych (tj. Nie specyficznymi dla pola), aby sprawdzić, czy spełniony jest jakiś warunek zewnętrzny, utknąłem w formularzu. Artykuł nie zagłębił się w to. Czy ktoś uprzejmie wskaże mi jakieś przydatne miejsce lub opublikuje je tutaj? Dzięki.
— colan

co jeśli musimy dodać istniejące sprawdzanie poprawności, takie jak \ Drupal \ user \ Form \ UserLoginForm :: validateName (). W wersji d7 było to proste: $ form ['# validate'] = array ('user_login_name_validate', 'myother_validaion',); Ale wygląda na to, że moduł no-contrib zaimplementował te zmiany drupal.org/node/2185941
— kiranking

8

Chcę dodać nieco więcej światła na ten temat. Dodanie sprawdzania poprawności jest dokładnie takie samo jak poprzednio: w hook_form_alter:

$form['#validate'][] = '_form_validation_number_title_validate';

Użycie obiektu wartości wewnątrz $ form_state w funkcji sprawdzania poprawności jest nieco inne. na przykład:

function _form_validation_number_title_validate(&$form, \Drupal\Core\Form\FormStateInterface $form_state) {

  if ($form_state->hasValue('title')) {
     $title = $form_state->getValue('title');

     if (!is_numeric($title[0]['value'])) {
        $form_state->setErrorByName('title', t('Your title should be number'));
     }

  }
}

Więc nie z bezpośrednim dostępem do obiektu zmiennych prywatnych, ale raczej z funkcją gettera.

Aby uzyskać więcej informacji, możesz zobaczyć pełny przykład w moim github: https://github.com/flesheater/drupal8_modules_experiments/blob/master/webham_formvalidation/webham_formvalidation.module

Twoje zdrowie!


Rzeczywiście jest. Tak jak napisałem w moim komentarzu powyżej. ;)
— AngularChef

7

Jest bardzo podobny do tego w D7. Kompletny przykład:

mymodule.module :

use Drupal\Core\Form\FormStateInterface;

/**
 * Implements hook_form_FORM_ID_alter() for the FORM_ID() form.
 */
function mymodule_form_FORM_ID_alter(&$form, FormStateInterface $form_state, $form_id) {
  $form['#validate'][] = '_mymodule_form_FORM_ID_validate';
}

/**
 * Validates submission values in the FORM_ID() form.
 */
function _mymodule_form_FORM_ID_validate(array &$form, FormStateInterface $form_state) {
  // Validation code here
}

To jest dość blisko. Potrzebny jest tylko hook_form_FORM_ID_alteridentyfikator formularza. Możesz mieć niestandardową funkcję sprawdzania poprawności dowolną. Należy również postępować zgodnie z instrukcją API tutaj, aby uzyskać odpowiednie parametry.
— mikeDOTexe,

Wcześniej, jak uzyskać identyfikator formularza, gdzie sprawdzić ten kod.
— logeshvaran

3

W uzupełnieniu tych dobrych odpowiedzi dodałbym:

$form['#validate'][] = 'Drupal\your_custom_module_name\CustomClass::customValidate';

To jak wywołać metodę klasy odległej w celu sprawdzenia poprawności formularza. Myślę, że lepiej jest wywołać powyższą funkcję w pliku modułu, tak jak w podanym przykładzie.


Nie ma już potrzeby przeskakiwania do kodu proceduralnego z OO.
— Colan

1

możesz użyć modułu weryfikacji klienta . Kilka dodatkowych szczegółów na ten temat (ze strony projektu):

... dodaje sprawdzanie poprawności po stronie klienta (zwane również „sprawdzaniem poprawności formularza Ajax”) dla wszystkich formularzy i formularzy internetowych za pomocą jquery.validate . Dołączony plik jquery.validate.js został załatany, ponieważ musieliśmy być w stanie ukryć puste wiadomości.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.