プログラムでフィールドを更新する、hook_node_update


13

現在、ノードが作成または更新されるたびにフィールドを更新しようとしています。ただし、値はノード内に入力されていません。この特定のフックを使用してノードオブジェクトにアクセスできますか?何が欠けているのでしょうか?

  function vbtoken_node_update($node) {


      entity_get_controller('node')->resetCache(array($node->nid));


      $types = node_type_get_types(); //What are the current Node Content Types?
      $yes = ($types['volunteer_project']->type);

      if($node->type === $yes){


        $hash = md5($node->title . $node->nid . $node->nid);
        $hashed = substr($hash, 0, 6);
        $node = node_load($node->nid);
        $node->tcode[$node->language][0]['value'] = $hashed;
        node_save($node);

        watchdog('vbtoken', 'Added a new Token code to %nid', array('%nid' => $node->nid));

        }
        else 
        {
          dpm('not working dude');
        }

    }

回答:


16

エンティティメタデータラッパー

エンティティAPIは、エンティティを簡単に処理し、提供されたエンティティプロパティ情報モジュールを活用するために使用できるラッパークラスを提供します。ラッパーの助けを借りて、プロパティ情報にアクセスしたり、既知のプロパティをループしたり、記述されたデータ値を取得/設定したりすることができます。

これらは、READMEにあるような簡単な使用例です。

この情報(メタデータ)を利用するために、モジュールは値の取得と設定を容易にするいくつかのラッパークラスを提供します。ラッパーは、エンティティプロパティのラッパーを取得するための連鎖使用をサポートします。たとえば、使用できるノード作成者のメールアドレスを取得します。

$wrapper = entity_metadata_wrapper('node', $node);
$wrapper->author->mail->value();

ユーザーのメールアドレスを更新するには

$wrapper->author->mail->set('sepp@example.com');

または

$wrapper->author->mail = 'sepp@example.com';

ラッパーは、プロパティ情報に記述されているように常にデータを返します。これは、entity_get_property_info()を介して直接、またはラッパーから取得できます。

$mail_info = $wrapper->author->mail->info();

出力用にサニタイズされたテキスト値を強制的に取得するには、たとえば

$wrapper->title->value(array('sanitize' => TRUE));

サニタイズされたノードのタイトルを取得します。ノード本体のように、プロパティが既にデフォルトでサニタイズされて返されている場合、ブラウザで他のユースケースに表示されるように、サニタイズされていないデータを取得したい場合があります。これを行うには、「デコード」オプションを有効にします。これにより、サニタイズされたデータのタグが削除され、プロパティが返される前にHTMLエンティティがデコードされます。

$wrapper->body->value->value(array('decode' => TRUE));

このようにして、ユーザーに表示されるデータを常に取得します。ただし、サニタイズされたテキストデータであっても、未処理の未処理の値を取得したい場合は、次の方法で取得できます。

$wrapper->body->value->raw();

その他の例:

$wrapper->body->set(array('value' => "content"));
$wrapper->field_text[0] = 'the text';
$wrapper->field_text[0]->set(array('value' => "content"));
$wrapper->field_text2->summary = 'the summary';
$wrapper->field_text2->value = 'the text';

$wrapper->save();
$wrapper->delete();

その他のドキュメントhttp : //drupal.org/node/1021556


どうもありがとうございます。あなたの答えは、私がしなければならないことへのいくつかの方向性を与えてくれました。:)コミュニティロックス!! \ m /
SGhosh

これはhook_node_updateでは機能しますが、hook_node_insert()では機能しません。ノードモジュールとカスタムコードの両方が(同じノードIDを使用して)同じノードを2回挿入しようとするため、mysqlから重複したプライマリキーエラーが発生します。
leon.nk

14

仕事field_attach_update('node', $node)の終わりに電話hook_node_updateをかけてきました。field_attach_insert('node', $node)終わりでhook_node_insertもうまくいくと思います。したがって、サンプル関数は次のようになります。

function mymodule_node_update($node) {
  $new_value = // ...do some stuff to compute a new value for the field.
  $node->field_my_field[LANGUAGE_NONE][0]['value'] = $new_value;
  field_attach_update('node', $node);
}

電話する必要はありません node_load node_saveたり、何かを返す。

私はこの理由は、ということだと思うnode_saveそこから、hook_node_updatehook_node_insert呼ばれ、トランザクション内のすべてのデータベースクエリをラップします。(の最初の行に注意node_save$transaction = db_transaction()。)これらのクエリはれるまで呼び出されませんnode_save終了します。node_saveトランザクションに追加する最後のクエリはfromから呼び出されfield_attach_update以前の $ nodeオブジェクトを使用してhook_node_update呼び出されます。そのため、field_attach_update再度呼び出すことで別のクエリをキューに入れる必要があります。少なくとも、それは何が起こっているのかの私の理解です。

ノードのフィールド以外の属性(など$node->log)を変更できない場合は、呼び出してみてください_node_save_revision($node, $user->uid, 'vid');。これは新しいリビジョンを作成しません。


2

これは、ノード上の値を変更する方法です。

$node = node_load($nodeID);
$node->field_fieldname['und'][0]['value'] = $val;
node_save($node);

4
und本当にOPはすでに、彼らが使用していることをコードで述べている、ここでは適切でない$node->language言語コードのために
クライヴ

CliveとLanceに感謝しますが、ノードが保存されるたびにフィールド値が保存されるようにしたいので、hook_node_updateを使用します。このフックで$ nodeを返すことは可能でしょうか、またはnode_loadを絶対に実行する必要がありますか?私は本当に....私はノードのオブジェクトがhook_node_update経由で直接渡さ思っていた
generalconsensus

わかりましたので、私はあなたの推奨に従ってコードを更新しました-それは元の本文にあります。問題:ページがロードされず、mysqlとapacheの両方がCPUで85%以上のロードを開始する無限ループ。間違いなくここでループが発生しています。他の提案はありますか?
一般的なコンセンサス

何が起こっているのかわかりません。ただし、ノードをロードして、フィールドに何かを入力し、node_save()を使用して保存するだけで済みます。それとも、負荷、ウォッチドッグまたはDPMを(使用して印刷何か()、これが動作するかどうかを確認するために、再度それを保存します。
ランス

この問題は、ノードを保存する前にノードを保存していたため、再帰的なループが発生していました。不適切なフックの選択と貧弱なビルド
一般的なコンセンサス

1

上記のLanceのソリューションの改善。少数のフィールド値のみが変更された場合にノード全体の保存を回避します。

$node = node_load($nodeID);
// for each field whose value remains unchanged
unset($node->field_<field-name>); 
// for each field whose value changes
$node->field_<field-name>[LANGUAGE_NONE][0]['value'] = <new-value>;
field_attach_update('node', $node);
entity_get_controller('node')->resetCache(array($node->nid));

これは、の副作用を回避するのにも役立ちnode_save()ます。

ソース:ノード自体を保存せずにノードのフィールドを保存する

https://www.urbaninsight.com/2011/10/24/saving-nodes-fields-without-saving-node-itself

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