web-dev-qa-db-ja.com

hook_form_alter()を使用してフォームデータを保存しましたが、UIからノードを編集するとデータが表示されません

いくつかのフィールドを挿入するためにhook_form_alter()を実装しました。フィールドデータを保存するhook_node_insert()hook_node_load()、およびhook_node_view()を実装しました。

すべて正常に動作しますが、ノードを編集すると、編集フォームがデータなしで表示されます。

どうすれば修正できますか?

function mymodule_form_ABC_node_form_alter(&$form, &$form_state, $form_id) {
  $options_first = _mymodule_get_first_dropdown_options();
  $selected = isset($form_state['values']['filed_1']) ? $form_state['values']['field_1'] : key($options_first);

  $form['field_1'] = array(
    // …
  );
  $form['field_2'] = array(
    // …
  );

  return $form;    
}

/**
 * Implements hook_node_insert().
 */
function mymodule_node_insert($node) {    
    db_insert('my_custom_table')
      ->fields(array('nid' => $node->nid, 'field_1' => $node->field_1, 'field_2' => $node->field_2,))
      ->execute();
}

/**
 * Implements hook_node_load().
 */
function mymodule_node_load($nodes, $types) {
  foreach ($nodes as $node) {
    $nids[] = $node->nid;
  }

  $result = db_select('custom_table', 'e')
    ->fields('e', array('nid', 'filed_1', 'field_2'))
    ->where('e.nid IN (:nids)', array(':nids' => $nids))
    ->execute();

  foreach ($result as $record) {
    $nodes[$record->nid]->field_1 = $record->field_1;
    $nodes[$record->nid]->field_2 = $record->field_2;
  }
}


/**
 * Implements hook_node_update().
 */
function mymodule_node_update($node) {
  if ($node->type == 'abc') {
    // Delete the existing values.
    db_delete('custom_table')
      ->condition('nid', $node->nid)
      ->execute();

    db_insert('custom_table')
      ->fields(array('nid' => $node->nid, 'field_1' => $node->field_1, 'field_2' => $node->field_2,))
      ->execute();
  }
}
3
Waqas

コードが行うことは、Bookモジュールが book_form_node_form_alter()book_node_load() 、および book_node_insert() を使用して行うことと似ています。

あなたのコードの何が間違っているのですか?

  • mymodule_form_ABC_node_form_alter()では、mymodule_node_load()でロードした値からフォームフィールドを初期化しません。つまり、使用しているフォームフィールドは常に空の文字列に設定されます。 Bookモジュールは_$form_state['values']['book']_を使用して_$node->book_を初期化しますが、 _ book_add_form_elements() に関するコメントは、その理由を説明しています。

    _// If the form is being processed during the Ajax callback of our book bid
    // dropdown, then $form_state will hold the value that was selected.
    if (isset($form_state['values']['book'])) {
      $node->book = $form_state['values']['book'];
    }
    _
  • hook_node_insert() を実装しますが、 hook_node_update() は実装しません。つまり、使用しているノードプロパティの値は、ノードの更新時ではなく、ノードの作成時に保存されます。

Bookモジュールは hook_node_prepare()book_node_prepare() )を実装していることは事実ですが、その目的は、処理するノードプロパティのデフォルト値を設定することだけであり、これは便利ですノードがユーザーインターフェイスを介して作成されていない場合。

コンテンツタイプがabcのときにこれらのノードプロパティを保存することに関心があるので、次のようにコードを実装します。

_function mymodule_form_abc_node_form_alter(&$form, &$form_state, $form_id) {
  $node = $form['#node'];
  $options_first = _mymodule_get_first_dropdown_options();
  $selected = !empty($node->field_1) ? $node->field_1 : key($options_first);

  $form['field_1'] = array(
    // …
  );
  $form['field_2'] = array(
    // …
  );

  return $form;    
}

function mymodule_node_prepare($node) {
  if ($node->type == 'abc') {
    $node->field_1 = '';
    $node->field_2 = '';
  }
}

function mymodule_node_load($nodes, $types) {
  $nids = array();

  foreach ($nodes as $nid => $node) {
    if ($node->type == 'abc') {
      $nids[] = $nid;
    }
  }

  if (!empty($nids)) {
    db_query('SELECT e.nid, e.field_1, e.field_2 FROM {custom_table} e WHERE e.nid IN :nids'), array(':nids' => $nids), array('fetch' => PDO::FETCH_ASSOC));

    foreach ($result as $record) {
      $nodes[$record['nid']]->field_1 = $record['field_1'];
      $nodes[$record['nid']]->field_2 = $record['field_2'];
    }
  }
}

/**
 * Implements hook_node_insert().
 */
function mymodule_node_insert($node) {
  // hook_node_insert() is called for any node.
  // Check the content type of the node is the one for which the form fields have been added.
  if ($node->type == 'abc') {
    $values['field_1'] = !empty($node->field_1) ? $node->field_1 : '';
    $values['field_2'] = !empty($node->field_2) ? $node->field_2 : '';

    db_insert('my_custom_table')
      ->fields(array('nid' => $node->nid, 'field_1' => $values['field_1'], 'field_2' => $values['field_2']))
      ->execute();
  }
}

/**
 * Implements hook_node_update().
 */
function mymodule_node_update($node) {
  if ($node->type == 'abc') {
    db_update('custom_table')
      ->condition('nid' => $node->nid)
      ->fields(array('field_1' => $node->field_1, 'field_2' => $node->field_2))
      ->execute();
  }
}
_

動的クエリは、別のモジュールが変更するなど、厳密に必要な場合に使用する必要があります。動的クエリを使用する必要がある場合は、次のように書き直します。

_$result = db_select('custom_table', 'e')
  ->fields('e', array('nid', 'filed_1', 'field_2'))
  ->condition('nid', $nids, 'IN')
  ->execute();
_

データベースの値を更新するには、 db_update() を使用する必要があります。データベースにすでに存在する値は削除せず、新しい値を挿入します。 db_update()は、$query->condition()で表される条件に一致するデータベース行を探し、$query->fields()で指定されたフィールドを新しい値で更新します。

補足として、すでにインストールされて有効になっているモジュールを編集している場合は、無効にしてから再度有効にする必要があります。そうしないと、Drupalはコードが変更されたことに気付かず、新しいモジュールを実装しますフック。 Drupalは、有効なモジュールから実装されたフックのリストをキャッシュに保持します。モジュールを無効にして再度有効にすると、Drupalがそのキャッシュを強制的に更新します。

1
kiamlaluno

hook_node_prepare を実装する必要があります。このフックは、ノードオブジェクトが追加/編集フォームに表示される前に追加データをロードするために使用されます。

1
Eugene Fidelin