プログラムでフィールドのすべてのインスタンスを検証する


7

プログラムでフィールドのすべてのインスタンスを検証する最良の方法(フック)は何ですか?のような同じフィールドを持つ多くのコンテンツタイプがありますfield_phonefield_phone使用されているすべての場所をプログラムで検証したい。


1
これは1回限りの評価ですか、それとも常に適用したいものですか?常に適用する必要がある場合は、フィールドの検証を通常どおり追加し、そのフィールドを含むすべてのノードを再度保存できます...
Patrick Kenny

@PatrickKennyそのためのモジュールを書きたい。
hpn 2013

1
しかし、すべてのデータを一度だけ再検証するモジュール、または各送信時にどこでもそれを検証するモジュール?
Mołot

フォームフィールドの生成中に検証関数を指定します。
2013

@Mołot各送信でどこでも検証できるモジュール
hpn

回答:


6

あなたはhook_field_validateを実装し、その正しいインスタンスであるかどうかを確認することができます。フィールドがモジュールによって定義されていない場合は機能しません。

フォームにフィールドが存在する場合、hook_form_alterを使用してelement_validatorを追加する方法の1つを作成します

function mymodule_form_alter(&$form, &$form_state, $form_id) {
   if (isset($form['field_phone'])) {
      $form['field_phone']['#element_validate'][] = 'mymodule_somevalidator';
    }
 }

function mymodule_somevalidator($element, &$form_state) {
  if (!empty($element['#value']) && !is_numeric(parse_size($element['#value'])) {
    form_error($element, t('The "!name" must be x', array('!name' => t($element['title']))));
  }
} 

1
hook_field_validateは機能しません。それは悪魔のタイプを定義するモジュールによって実装されるフックです。代わりに、hook_field_attach_validateを実装することもできます。
ジョンハッタン2013

@jonhattan:回答を編集しました。あなたが正しい、おそらくフィールドはモジュールによって定義されていません。
user20301 2013

これは私に小さな変更を加えて機能しました:$ element ['#value']の代わりに、$ element [$ element ['#language']] [0] ['#value']と$ elementの代わりに使用する必要がありました。 ['title']、$ element [$ element ['#language']] [0] ['#title']を使用する必要がありました。お役に立てれば。
Supriya Rajgopal 2017年


2

field_attach_form_validateから:

フォームのフィールドの検証には、ウィジェット検証とフィールド検証の2つのレベルがあります。

ウィジェットの検証では、hook_form_alterパスをたどることができます。フォームの構築方法の詳細を知る必要があるため、これを一般化するのは困難です。たとえば、一部のエンティティでは要素または値がネストされている場合があります。

IMO、フィールド検証を行うのが最善です。これは、hook_field_attach_validateを実装することによって実行され ます。以下に簡単な例を示します。

function hook_field_attach_validate($entity_type, $entity, &$errors) {
  if (isset($entity->field_phone)) {
    $errors['field_phone'][LANGUAGE_NONE][0][] = array(
      'error' => 'error_key',
      'message' => t('Error message'),
    );
  }
}

error_keyウィジェットが複数の要素の複合である場合に、hook_field_widget_errorによってフォーム要素にフラグを付けるために使用されます。たとえば、このフックのテキストフィールドの実装でtext_summary_max_lengthは、ウィジェット構造内の要素にフラグを立てるためにエラーキーが使用されます。

一般的な用語では、エラーキーは単一の要素を持つウィジェットには使用されません。以下の場合は電話フィールドタイプ(私はあなたが使用していると仮定していること)、彼らは化合物ウィジェットを提供しますが、要素に誤差分布を実装していないので、ちょうどそれを無視し、。


1

hook_form_alterを実装することによってそれを実装する最良の方法。ロジックは、field_phone(あなたの場合)のように同じフィールドを持つすべてのコンテンツタイプフォームに対してカスタム検証関数を追加する必要があり、動的である必要があるようなものです。かつて私はそのような状況に遭遇しましたが、単一のフォームに対して検証する必要がありました。以下のコードはほとんど同じ実装ですが、私はあなたの場合のためにそれをはるかに動的にしました。

モジュールを作成し、次のようにhook_form_alterを実装します。

/**
 * Implementation of hook_form_alter
 */
function MODULE_NAME_form_alter(&$form, $form_state, $form_id) {
  // $cck_type contains the array of all Drupal content type machine names
  $cck_type = array_keys(node_type_get_types());

  // Machine names of those content type whose instance you want to validate
  // Add your machine name for whom you want to validate. You can get the 
  // machine names of content types from Admin > Structure > Content types. Fill
  // as many required bu you.
  $my_types = array('CCK_TYPE_1', 'CCK_TYPE_2', 'CCK_TYPE_3');

  // Since, a user fill one form at particular time. The variable $current_type 
  // hold the Content Type machine name for current form. 
  if (arg(0) == 'node' && arg(1) == 'add') {
    $current_type = arg(2);
  } elseif ((arg(0) == 'node') && is_numeric(arg(1)) && (arg(2) == 'edit')) {
    $node = node_load(arg(1));
    $current_type = $node->type;
  }

  // gets current form's ID
  $id_of_form = $form['form_id']['#value'];

  // checks if the current form is part of Drupal Content Type
  if (in_array($current_type, $my_types) && in_array($current_type, $cck_type)) {
    $id_of_form = $form['form_id']['#value'];
    if ($form_id == $id_of_form) {
      // Adding custom validation function to the form so that we can validate
      // the field of that form
      $form['#validate'][] = 'custom_validates';
    }
  }
}

次に、検証用のカスタム検証関数を実装します。

/**
 * Implementation of custom validation for validating 'field_phone' in your case.
 * It can be any field, assuming that it is part of that form.
 */
function custom_validates(&$form, $form_state) {
  $values = $form_state['values'];

  // Language of the $form
  $lang = $form['language']['#value'];
  $field_phone = $values['field_phone'][$lang][0]['value'];

  // In my case, for testing purpose, I had set the strings in Phone field
  if (!is_integer($field_phone)) {
    form_set_error('field_phone', 'Invalid phone number');
  }
}

単純なアプローチで$form_idは、コンテンツタイプフォームのを確認し、次のようなカスタム検証関数を追加するだけです。

/**
 * Implementation of hook_form_alter
 */
function MODULE_NAME_form_alter(&$form, $form_state, $form_id) {
  if (($form_id == 'content_type_form_id_1') ||
          ($form_id == 'content_type_form_id_2') ||
          ($form_id == 'content_type_form_id_3')) {
    // Adding custom validation function to the form so that we can validate
    // the field of that form
    $form['#validate'][] = 'custom_validates';
  }
}

しかし、この単純なアプローチの問題は、すべての単一のコンテンツタイプフォームのフォームIDを知ってから、それを||以前に示したように演算子付きのifステートメントに追加する必要があることです。これには多くの時間がかかります。

ロジックと実装を理解していただくために、それぞれコメントしました。

私の解決策があなたの問題を解決することを願っています。


0

私の意見では、答えはhook_field_widget_WIDGET_TYPE_form_alter()です。フックを使用して検証コールバックを$ element [#element_validate]配列に追加すれば、準備は完了です。

hook_form_alter()は非常に一般的であり、field_phoneがあるかどうかに関係なく、すべてのフォームに対して呼び出されます(オーバーヘッドが増加します)。さらに、field_phoneがさまざまなフィールドセットまたはコンテナの内部にある場合はどうなりますか?再帰的に探す必要があります(追加のオーバーヘッド)。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.