Überprüfen Sie alle Instanzen eines Feldes programmgesteuert

7

Was ist der beste Weg (Hook), um alle Instanzen eines Feldes programmgesteuert zu validieren? Ich habe viele Inhaltstypen mit den gleichen Feldern wie field_phone. Ich möchte programmgesteuert field_phoneüberall dort validieren, wo es verwendet wird.

hpn
quelle
1
Ist dies eine einmalige Bewertung oder etwas, das Sie immer anwenden möchten? Wenn es immer angewendet werden soll, können Sie die Feldvalidierung einfach normal hinzufügen und dann alle Knoten mit diesem Feld erneut speichern ...
Patrick Kenny
@PatrickKenny Ich möchte ein Modul dafür schreiben.
HPN
1
Aber ein Modul, um alle Ihre Daten einmalig zu validieren, oder ein Modul, um sie bei jeder Übermittlung überall zu validieren?
Mołot
Geben Sie die Validierungsfunktion beim Generieren des Formularfelds an.
halten
@ Mołot ein Modul, um es überall bei jeder Einreichung zu validieren
HPN

Antworten:

6

Sie können hook_field_validate implementieren und prüfen, ob es die richtige Instanz ist. Funktioniert nicht, wenn das Feld nicht vom Modul definiert wird.

Eine Möglichkeit zum Erstellen, bei der hook_form_alter verwendet und element_validator hinzugefügt wird, wenn das Feld im Formular vorhanden ist.

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']))));
  }
} 
user20301
quelle
1
hook_field_validate funktioniert nicht. Es ist ein Hook, der von Modulen implementiert wird, die Unhold-Typen definieren. Möglicherweise möchten Sie stattdessen hook_field_attach_validate implementieren .
Jonathan
@ Jonathan: Die Antwort wurde bearbeitet. Sie haben Recht, höchstwahrscheinlich wird das Feld nicht vom Modul definiert.
user20301
Dies funktionierte bei mir mit einer geringfügigen Änderung: Anstelle von $ element ['# value'] musste ich $ element [$ element ['# language']] [0] ['# value'] und anstelle von $ element verwenden ['title'] musste ich $ element [$ element ['# language']] [0] ['# title'] verwenden. Hoffe das hilft.
Supriya Rajgopal
4

Probieren Sie das Feldvalidierungsmodul aus .

Sie müssen jedem Feld, das Sie validieren möchten, noch eine ordnungsgemäße Validierung hinzufügen.

Scott Joudry
quelle
2

Von field_attach_form_validate :

Es gibt zwei Validierungsstufen für Felder in Formularen: Widget-Validierung und Feldvalidierung.

Für die Widget-Validierung können Sie dem Pfad hook_form_alter folgen. Dies ist schwer zu verallgemeinern, da Sie Details darüber wissen müssen, wie das Formular erstellt wird. Beispielsweise können Elemente oder Werte für einige Entitäten verschachtelt sein.

IMO, es ist am besten, eine Feldvalidierung durchzuführen. Dies erfolgt durch Implementierung von hook_field_attach_validate . Hier ist ein einfaches Beispiel:

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_keywird von hook_field_widget_error verwendet, um ein Formularelement zu kennzeichnen , wenn ein Widget aus mehreren Elementen besteht. Beispielsweise wird bei der Implementierung dieses Hooks durch ein Textfeld der Fehlerschlüssel text_summary_max_lengthverwendet, um ein Element innerhalb der Widget-Struktur zu kennzeichnen.

Im Allgemeinen wird der Fehlerschlüssel nicht für Widgets mit einem einzelnen Element verwendet. Im Fall eines Telefonfeldtyps (von dem ich annehme, dass Sie ihn verwenden) stellen sie ein zusammengesetztes Widget bereit, implementieren jedoch keine Fehlerverteilung auf Elemente . Ignorieren Sie es einfach.

jonhattan
quelle
1

Der beste Weg, um es zu implementieren, indem Sie hook_form_alter implementieren . Die Logik ist so, dass Sie die benutzerdefinierte Validierungsfunktion für alle Inhaltstypformulare hinzufügen müssen, die dasselbe Feld wie field_phone(in Ihrem Fall) haben und dynamisch sein müssen. Einmal war ich auf eine solche Situation gestoßen, musste mich aber gegen das einzelne Formular validieren. Der folgende Code ist fast dieselbe Implementierung, aber ich habe ihn für Ihren Fall viel dynamischer gestaltet.

Erstellen Sie ein Modul und implementieren Sie hook_form_alter wie folgt :

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

Implementieren Sie jetzt die benutzerdefinierte Validierungsfunktion zur Validierung.

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

Bei dem einfachen Ansatz müssen Sie nur das $form_idFormular Ihres Inhaltstyps überprüfen und die benutzerdefinierte Validierungsfunktion wie folgt hinzufügen:

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

Das Problem bei diesem einfachen Ansatz besteht jedoch darin, dass Sie die Formular-ID jedes einzelnen Formulars für den Inhaltstyp kennen und diese dann ||wie zuvor gezeigt zur if-Anweisung mit dem Operator hinzufügen müssen. Dies wird viel Zeit in Anspruch nehmen.

Ich habe entsprechende Kommentare abgegeben, damit Sie die Logik und Implementierung verstehen.

Ich hoffe, dass meine Lösung Ihr Problem beantwortet.

Asad
quelle
0

Die Antwort lautet meiner Meinung nach hook_field_widget_WIDGET_TYPE_form_alter () . Verwenden Sie den Hook, um Ihren Validierungsrückruf zum Array $ element [#element_validate] hinzuzufügen, und Sie können loslegen .

hook_form_alter () ist sehr allgemein und wird für jedes Formular aufgerufen, unabhängig davon, ob es field_phone hat oder nicht (zunehmender Overhead). Was ist außerdem, wenn sich das field_phone tief in verschiedenen Feldsätzen oder Containern befindet? Sie müssen rekursiv danach suchen (zusätzlicher Aufwand).

Jigarius
quelle