기존 양식 / 필드에 사용자 정의 유효성 검증 핸들러를 추가하려면 어떻게합니까?


21

Drupal 8의 기존 양식 (또는 양식 필드)에 사용자 정의 유효성 검사 핸들러를 추가하려면 어떻게합니까?

작성하지 않은 양식이 있습니다. 양식을 제출할 때 일부 필드에 자체 검증 규칙을 추가하고 싶습니다.

Drupal 7의 경우 양식에 대한 사용자 지정 유효성 검사? hook_form_alter()유효성 검사 핸들러 를 구현 한 다음 $form['#validate']배열에 추가하는 방법] [1]을 배열에 설명하지만 Drupal 8 형식에는 클래스가 있습니다. 유효성 검사는 validateForm()메소드를 통해 수행 되며 코드를 코드에 연결하는 방법을 모르겠습니다.



1
정확히 중복되지는 않습니다. 내 질문은 D8에 대한 것이고, 귀하의 링크는 D7에 대한 것입니다.
AngularChef

나는 오늘 이것을 보았고 POST를 사용하지 않는 경우 (기존보기 페이지에 URL 제출을 원했다면) validateForm이나 submitForm이 실행되지 않는 경우 다른 사람들에게 주목하고 싶었습니다. 가늠자에서 이것은 명백하다.… 그러나 나는
깨 달기

답변:


19

#validate속성 은 Drupal 8에서 여전히 사용됩니다 (Adi의 솔루션을 사용하면 기존 유효성 검사기를 재정의 함)

기본값 외에도 사용자 정의 유효성 검사기를 추가하려면 hook_form_FORM_ID_alter (또는 이와 유사한)에 다음과 같은 것을 추가해야합니다 .

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

고마워요, Shabir. 따라서 사용자 지정 유효성 검사기를 추가하면 D7 및 D8에서 동일하게 작동합니다. ;)
AngularChef

정확히, 노드 모듈의 코드를 참조하십시오. 거기에 많은 예가 있습니다
Shabir A.

2
방금 시도했지만 완벽하게 작동했습니다. 감사합니다. D8 Form API Reference가 #validate(링크)에 대해 말한 것과 달리 $form_state배열 (D7 방식)이 아니라 구현 FormStateInterface(D8 방식)으로 사용해야 합니다 . 즉, 사용자 정의 유효성 검사기의 코드는 원래 validateForm()방법 에서 찾은 코드와 유사해야합니다 .
AngularChef

25

Berdir은 Drupal 8의 필드에 유효성 검사를 추가하는 데 제약 조건이 올바른 방법이라는 정답을 제시했습니다. 다음은 예입니다.

아래 예에서는 podcast단일 값 필드가있는 유형의 노드로 작업 합니다 field_podcast_duration. 이 필드의 값은 HH : MM : SS (시간, 분 및 초) 형식이어야합니다.

제약 조건을 만들려면 두 개의 클래스를 추가해야합니다. 첫 번째는 제약 조건 정의이고 두 번째는 제약 조건 유효성 검사기입니다. 둘 다 네임 스페이스의 플러그인입니다 Drupal\[MODULENAME]\Plugin\Validation\Constraint.

먼저 구속 조건 정의입니다. 플러그인 ID는 클래스의 주석 (설명)에 'PodcastDuration'으로 제공됩니다. 이것은 아래로 더 사용됩니다.

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';
}

다음으로 제약 검증기를 제공해야합니다. 이 클래스의 이름은 위에서 Validator추가 한 클래스 이름이 됩니다.

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]);
    }
  }
}

마지막으로 Drupal에 노드 유형 field_podcast_duration에 대한 제약 조건을 사용하도록 지시해야 podcast합니다. 우리는 이것을 다음과 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');
  }
}

필드를 검증하기 위해 다른 필드 값이 필요한 경우 컨텐츠 유형에 제한 조건을 추가 할 수 있습니다. 이 블로그 게시물을 참조하십시오 : lakshminp.com/entity-validation-drupal-8-part-2
엄만

1
D8 양식 검증 API는 Drupal.org에 자세히 설명되어 있습니다. 맞춤형 검증 제약 조건 제공
Sukhjinder Singh

1
이 질문은 특히 필드 API가 아닌 양식 API에 관한 것이므로 엔티티 필드가 아닌 양식 요소에이 제약 조건을 어떻게 적용합니까?
aaronbauman

양식 요소는 제약 조건을 가질 수 없습니다. #element_validate를 사용하여 특정 양식 요소에 유효성 검사를 추가 할 수 있습니다. 이 글타래에 대한 답변은 D7에서와 동일하게 작동합니다. drupal.stackexchange.com/questions/86990/…
Jaypan

$item = $items->first();필드를 편집 할 때 아무것도 없거나 그렇지 않은 경우 NULL 을 확인 하고 리턴 하는지 확인하십시오 . TypeError : Drupal \ Component \ Utility \ NestedArray :: getValue ()에 전달 된 인수 2는 유형 배열이어야합니다. null이 주어졌으며 Drupal \ Component \ Utility \ NestedArray :: getValue ()의 407 행에있는 /data/app/core/lib/Drupal/Core/Field/WidgetBase.php에서 호출되었습니다 (core / lib / Drupal / Component의 69 행). /Utility/NestedArray.php).
Ivan Zugec

16

노드와 같은 컨텐츠 엔티티에 대해이를 수행하는 올바른 방법은이를 제한 조건으로 등록하는 것입니다.

참조 forum_entity_bundle_field_info_alter()및 해당? ForumLeaf유효성 검증 제한 조건 (두 개의 클래스가 필요함).

처음에는 조금 더 복잡하지만 이점은 유효성 검사 API에 통합되어 있으므로 유효성 검사가 양식 시스템으로 제한되지 않고 REST API를 통해 제출 된 노드에서 작동 할 수 있다는 것입니다.


좋은 점 : 이것은 Drupal 7의 코드를 작성했던 사람들에게 새로운 것입니다. 제약 조건이 더 적절한 경우 유효성 검사 핸들러를 추가하려고하는 많은 사용자가 있습니다.
kiamlaluno

Berdir : hook_entity_bundle_field_info_alter()( 여기에 설명 된대로 ) 구현하려고 시도하여이 옵션을 탐색 했지만 작동하지 않았습니다 ...이 후크에 문서화 된 문제가있는 것 같습니다 : drupal.org/node/2346347 .
AngularChef 2016

몇 가지 문제가 있지만 문제와 관련이 있다고 생각하지 않습니다. forum.module이 작동 함을 보여줍니다. 코드를 공유하십시오. 그렇지 않으면 구현에서 가능한 문제를 지적 할 수 없습니다.
Berdir

1
이 방법을 사용하고 싶지만 외부 조건이 충족되는지 확인하기 위해 데이터 유형과 함께 사용하는 방법에 대한 좋은 예가있을 때까지 (예 : 필드 특정이 아님), 양식 변경이 붙어 있습니다. 기사는 이것을 파헤 치지 않았습니다. 누군가가 친절하게 나를 어딘가에 친절하게 지적하거나 여기에 게시하겠습니까? 감사.
colan

\ Drupal \ user \ Form \ UserLoginForm :: validateName ()과 같은 기존 유효성 검사를 추가해야하는 경우 어떻게해야합니까? d7에서는 $ form [ '# validate'] = array ( 'user_login_name_validate', 'myother_validaion',); 그러나이 변경 사항을 구현하지 않은 모듈은 drupal.org/node/2185941
18:41에

8

이 문제에 대해 좀 더 밝히고 싶습니다. 유효성 검사를 추가하는 것은 전과 동일합니다 : hook_form_alter에서 :

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

validate 함수에서 $ form_state 내부의 values ​​객체 사용은 약간 다릅니다. 예 :

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'));
     }

  }
}

따라서 개인 변수 객체에 직접 액세스하는 것이 아니라 getter 함수를 사용하십시오.

자세한 내용은 내 github에서 전체 예제를 볼 수 있습니다 : https://github.com/flesheater/drupal8_modules_experiments/blob/master/webham_formvalidation/webham_formvalidation.module

건배!


실제로 그렇습니다. 위의 의견에 쓴 것처럼. ;)
AngularChef

7

D7과 거의 동일합니다. 완전한 예 :

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
}

이것은 매우 가깝습니다. hook_form_FORM_ID_alter양식 ID 만 있으면 됩니다. 사용자 정의 유효성 검사 기능을 원하는 것으로 지정할 수 있습니다. 또한 적절한 매개 변수에 대해서는 API 안내서를 따르십시오 .
mikeDOTexe

그 전에 폼 ID를 얻는 방법,이 코드를 확인할 위치.
logeshvaran

3

이 좋은 답변을 보완하기 위해 다음을 추가합니다.

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

폼 유효성 검사를 위해 먼 클래스 메서드를 호출하는 방법입니다. 주어진 예제와 같이 모듈 파일에서 위의 함수를 호출하는 것이 좋습니다.


더 이상 OO에서 절차 코드로 건너 뛸 필요가 없습니다.
colan

1

Clientside Validation 모듈을 사용할 수 있습니다 . 이에 대한 자세한 내용은 (프로젝트 페이지에서) :

... jquery.validate를 사용하여 모든 양식 및 웹 양식에 대한 클라이언트 측 유효성 검사 ( "Ajax 양식 유효성 검사")를 추가합니다 . 포함 된 jquery.validate.js 파일은 빈 메시지를 숨길 수 있어야하기 때문에 패치되었습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.