ฉันจะเพิ่มตัวจัดการการตรวจสอบความถูกต้องที่กำหนดเองให้กับฟอร์ม / ฟิลด์ที่มีอยู่ได้อย่างไร


21

ฉันจะเพิ่มตัวจัดการการตรวจสอบความถูกต้องที่กำหนดเองไปยังแบบฟอร์มที่มีอยู่ (หรือเขตข้อมูลฟอร์ม) ใน Drupal 8 ได้อย่างไร

ฉันมีแบบฟอร์มที่ฉันไม่ได้สร้าง ฉันต้องการเพิ่มกฎการตรวจสอบของตัวเองในบางฟิลด์เมื่อส่งแบบฟอร์ม

สำหรับ Drupal 7 การตรวจสอบความถูกต้องที่กำหนดเองสำหรับฟอร์ม อธิบายถึงการนำไปใช้hook_form_alter()แล้วเพิ่มเครื่องมือตรวจสอบความถูกต้องของคุณ] [1] ใน$form['#validate']อาร์เรย์ แต่ในรูปแบบ Drupal 8 เป็นคลาส การตรวจสอบทำได้ผ่านvalidateForm()วิธีการและฉันไม่รู้วิธีเสียบรหัสของฉันลงในนั้น



1
มันไม่ซ้ำกันอย่างแน่นอน คำถามของฉันสำหรับ D8 ลิงค์ของคุณสำหรับ D7
AngularChef

ฉันเจอสิ่งนี้ในวันนี้และแค่อยากจะให้คนอื่นรู้ถ้าคุณไม่ได้ใช้ POST (ฉันต้องการส่ง URL ไปยังหน้ามุมมองที่มีอยู่) ไม่ใช่ validateForm หรือ sendForm run ในการเข้าใจถึงปัญหานี้ชัดเจน .... แต่ฉันใช้เวลา 30 นาทีพยายามคิดออกก่อนที่ฉันจะรู้ .... : /
ben.hamelin

คำตอบ:


19

#validateอสังหาริมทรัพย์ยังคงใช้ใน Drupal 8. (ด้วยวิธี Adi ของคุณจะแทนที่การตรวจสอบที่มีอยู่)

หากคุณต้องการเพิ่มเครื่องมือตรวจสอบที่กำหนดเองของคุณนอกเหนือจากค่าเริ่มต้นคุณจะต้องเพิ่มสิ่งนี้ในhook_form_FORM_ID_alter (หรือคล้ายกัน):

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

ขอบคุณ Shabir ดังนั้นการเพิ่มตัวตรวจสอบความถูกต้องที่กำหนดเองจะทำงานได้เหมือนกันใน D7 และ D8 ;)
AngularChef

ตรวจสอบโค้ดของโมดูลโหนด มีตัวอย่างมากมายที่นั่น
Shabir A.

2
ฉันเพิ่งลองและมันทำงานได้อย่างสมบูรณ์ขอบคุณ โปรดทราบว่าตรงกันข้ามกับสิ่งที่การอ้างอิงแบบฟอร์ม API ของ D8 บอกไว้สำหรับ#validate(ลิงก์ของคุณ) คุณไม่ควรใช้$form_stateเป็นอาร์เรย์ (วิธี D7) แต่เป็นวัตถุที่นำไปใช้งานFormStateInterface(วิธี D8) กล่าวอีกนัยหนึ่งรหัสในเครื่องมือตรวจสอบที่กำหนดเองของคุณควรตรงกับรหัสที่คุณค้นหาในvalidateForm()วิธีการดั้งเดิม
AngularChef

25

Berdir ให้คำตอบที่ถูกต้องว่าข้อ จำกัด เป็นวิธีที่ถูกต้องในการเพิ่มการตรวจสอบความถูกต้องไปยังเขตข้อมูลใน Drupal 8 นี่คือตัวอย่าง

ในตัวอย่างด้านล่างเราจะได้ร่วมงานกับโหนดของประเภทที่มีข้อมูลค่าเดียวpodcast field_podcast_durationค่าสำหรับฟิลด์นี้จะต้องจัดรูปแบบเป็น HH: MM: SS (ชั่วโมงนาทีและวินาที)

ในการสร้างข้อ จำกัด ต้องเพิ่มสองคลาส ประการแรกคือคำจำกัดความของข้อ จำกัด และข้อที่สองคือตัวตรวจสอบข้อ จำกัด ทั้งสองมีปลั๊กอินใน namespace 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
ummdorian

1
API การตรวจสอบความถูกต้องของฟอร์ม D8 ได้รับการอธิบายโดยละเอียดเกี่ยวกับ Drupal.org ที่นี่ ให้ข้อ จำกัด การตรวจสอบที่กำหนดเอง
Sukhjinder ซิงห์

1
เนื่องจากคำถามนี้เกี่ยวกับ Form API ไม่ใช่ไม่ใช่ Field API เราจะแนบข้อ จำกัด นี้เข้ากับองค์ประกอบของฟอร์มได้อย่างไร (ไม่ใช่ฟิลด์เอนทิตี)
aaronbauman

องค์ประกอบของแบบฟอร์มต้องไม่มีข้อ จำกัด คุณสามารถเพิ่มการตรวจสอบความถูกต้องให้กับองค์ประกอบแบบฟอร์มโดยใช้ #element_validate ดูคำตอบที่ดีที่สุดในหัวข้อนี้ - มันทำงานได้เหมือนกันใน D8 เป็น D7 drupal.stackexchange.com/questions/86990/…
Jaypan

ตรวจสอบให้แน่ใจว่าคุณได้ตรวจสอบ$item = $items->first();และส่งคืนค่า NULL หากไม่มีสิ่งใดเกิดขึ้นหรือคุณจะได้รับข้อผิดพลาดร้ายแรงเมื่อแก้ไขฟิลด์: TypeError: อาร์กิวเมนต์ 2 ที่ส่งผ่านไปยัง Drupal \ Component \ Utility \ NestedArray :: getValue () null ที่ระบุเรียกใน /data/app/core/lib/Drupal/Core/Field/WidgetBase.php บนบรรทัด 407 ใน Drupal \ Component \ Utility \ NestedArray :: getValue () (บรรทัดที่ 69 ของ core / lib / Drupal / Component /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

มีปัญหาบางอย่าง แต่ฉันไม่คิดว่าพวกเขาจะเกี่ยวข้องกับปัญหาของคุณ forum.module แสดงให้เห็นว่ามันใช้งานได้ แชร์รหัสของคุณเป็นไปไม่ได้ที่จะชี้ให้เห็นปัญหาที่อาจเกิดขึ้นในการนำไปใช้ของคุณ
Berdir

1
ฉันต้องการไปด้วยวิธีนี้ แต่จนกว่าจะมีตัวอย่างที่ดีของวิธีใช้กับชนิดข้อมูล (เช่นไม่ใช่ฟิลด์เฉพาะ) เพื่อตรวจสอบว่ามีเงื่อนไขภายนอกบางอย่างพบหรือไม่ฉันติดอยู่กับฟอร์มที่เปลี่ยนแปลง บทความไม่ได้ขุดลงในสิ่งนี้ ใครบางคนช่วยชี้ให้ฉันดูว่ามีประโยชน์หรือโพสต์ที่นี่ได้ไหม ขอบคุณ
colan

ถ้าเราต้องการเพิ่มการตรวจสอบที่มีอยู่เช่น \ Drupal \ user \ Form \ UserLoginForm :: validateName () ใน d7 มันง่ายเหมือน $ form ['# validate'] = array ('user_login_name_validate', 'myother_validaion',); แต่ดูเหมือนว่าโมดูลแบบไม่มีส่วนควบคุมจะนำการเปลี่ยนแปลงเหล่านี้ไปใช้drupal.org/node/2185941
kiranking

8

ฉันต้องการเพิ่มแสงเพิ่มเติมเกี่ยวกับเรื่องนี้ การเพิ่มการตรวจสอบความถูกต้องเหมือนกับใน: hook_form_alter:

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

การใช้วัตถุค่าภายใน $ form_state ในฟังก์ชั่นการตรวจสอบความถูกต้องแม้ว่าจะแตกต่างกันเล็กน้อย เช่น:

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

ก่อนหน้านั้นวิธีรับแบบฟอร์มรหัสเช่นกันที่จะตรวจสอบรหัสนี้
logeshvaran

3

เพื่อเติมเต็มของคำตอบที่ดีเหล่านี้ฉันจะเพิ่ม:

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

มันเป็นวิธีการเรียกวิธีการเรียนที่ห่างไกลสำหรับการตรวจสอบแบบฟอร์ม ฉันคิดว่ามันจะดีกว่าถ้าจะเรียกใช้ฟังก์ชันข้างต้นในไฟล์โมดูลเหมือนในตัวอย่างที่กำหนด


ไม่จำเป็นต้องข้ามไปยังโค้ดโพรซีเดอร์จาก OO อีกต่อไป
โคโล

1

คุณสามารถใช้โมดูลการตรวจสอบลูกค้า รายละเอียดเพิ่มเติมเกี่ยวกับมัน (จากหน้าโครงการ):

... เพิ่มการตรวจสอบ clientside (aka "ตรวจสอบรูปแบบอาแจ็กซ์") สำหรับทุกรูปแบบและ webforms ใช้jquery.validate ไฟล์ jquery.validate.js ที่รวมอยู่นั้นได้รับการแพตช์เพราะเราจำเป็นต้องซ่อนข้อความที่ว่างเปล่า

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.