Cập nhật trường theo lập trình, hook_node_update


13

Hiện đang cố gắng cập nhật một trường mỗi khi một nút được tạo hoặc cập nhật. Tuy nhiên, giá trị không được xác định trong nút, tôi có quyền truy cập vào đối tượng nút với hook cụ thể này không? Tôi có thể thiếu gì?

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

    }

Câu trả lời:


16

Các trình bao bọc siêu dữ liệu

API thực thể cung cấp một số lớp trình bao bọc mà bạn có thể sử dụng để dễ dàng xử lý các thực thể và tận dụng các mô đun thông tin thuộc tính thực thể được cung cấp. Với sự trợ giúp của các trình bao bọc, bạn có thể truy cập thông tin thuộc tính, lặp qua các thuộc tính đã biết hoặc chỉ nhận / đặt các giá trị dữ liệu được mô tả, v.v.

Đây là một số ví dụ sử dụng đơn giản như được tìm thấy trong README:

Để sử dụng thông tin này (siêu dữ liệu), mô-đun cung cấp một số lớp trình bao bọc giúp dễ dàng nhận và thiết lập các giá trị. Trình bao bọc hỗ trợ sử dụng chuỗi để truy xuất các trình bao bọc của các thuộc tính thực thể, ví dụ: để lấy địa chỉ thư của tác giả nút mà người ta có thể sử dụng:

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

Để cập nhật địa chỉ thư của người dùng, người ta có thể sử dụng

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

hoặc là

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

Các trình bao bọc luôn trả về dữ liệu như được mô tả trong thông tin thuộc tính, có thể được truy xuất trực tiếp qua entity_get_property_info () hoặc từ trình bao bọc:

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

Để buộc nhận được một giá trị văn bản được khử trùng cho đầu ra, người ta có thể sử dụng, ví dụ

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

để có được tiêu đề nút vệ sinh. Khi một thuộc tính đã được trả về vệ sinh theo mặc định, như thân nút, người ta có thể muốn lấy dữ liệu không được khử trùng như nó sẽ xuất hiện trong trình duyệt cho các trường hợp sử dụng khác. Để làm như vậy, người ta có thể kích hoạt tùy chọn 'giải mã', đảm bảo cho mọi dữ liệu được khử trùng, các thẻ bị tước và các thực thể HTML được giải mã trước khi thuộc tính được trả về:

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

Bằng cách đó, người ta luôn nhận được dữ liệu như hiển thị cho người dùng. Tuy nhiên, nếu bạn thực sự muốn nhận được giá trị thô, chưa xử lý, ngay cả đối với dữ liệu văn bản được khử trùng, bạn có thể thực hiện thông qua:

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

Ví dụ khác:

$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();

Thêm tài liệu : http://drupal.org/node/1021556


Cảm ơn bạn rất nhiều. Câu trả lời của bạn đã giúp tôi có một số hướng cho những gì tôi phải làm. :) Cộng đồng đá !! \ m /
SGhosh

Điều này sẽ hoạt động trên hook_node_update nhưng không hoạt động trên hook_node_insert (). Bạn sẽ nhận được một lỗi khóa chính trùng lặp từ mysql, vì cả mô-đun nút và mã tùy chỉnh của bạn sẽ cố gắng chèn cùng một nút hai lần (sử dụng cùng một id nút).
leon.nk

14

Gọi field_attach_update('node', $node)vào cuối hook_node_updatelàm việc cho tôi. Tôi cho rằng field_attach_insert('node', $node)vào cuối của hook_node_insertquá sẽ làm việc, quá. Vì vậy, một hàm mẫu sẽ trông như thế này:

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);
}

Không cần phải gọi node_load node_savehoặc trả lại bất cứ điều gì.

Tôi nghĩ lý do cho điều này là node_save, từ đó hook_node_updatehook_node_insertđược gọi, bao bọc tất cả các truy vấn cơ sở dữ liệu trong một giao dịch. (Lưu ý dòng đầu tiên của node_save: $transaction = db_transaction().) Các truy vấn này không được gọi cho đến khi node_savekết thúc. Truy vấn cuối cùng node_savethêm vào giao dịch được gọi từ field_attach_update, sử dụng đối tượng nút $ như trước đây hook_node_update được gọi. Vì vậy, bạn cần phải xếp hàng một truy vấn khác bằng cách gọi field_attach_updatelại. Ít nhất, đó là sự hiểu biết của tôi về những gì đang xảy ra.

Nếu bạn gặp sự cố khi thay đổi các thuộc tính phi trường của nút (ví dụ $node->log:), hãy thử gọi _node_save_revision($node, $user->uid, 'vid');. Điều này sẽ không tạo ra một phiên bản mới.


2

Đây là cách bạn thay đổi giá trị trên một nút:

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

4
undở đây không thực sự thích hợp, OP đã tuyên bố trong mã mà họ đang sử dụng $node->languagecho mã ngôn ngữ
Clive

Điều đó siêu hữu ích nhờ Clive và Lance, nhưng tôi muốn đảm bảo giá trị trường được lưu bất cứ khi nào nút được lưu, do đó tôi sử dụng hook_node_update. Tôi có thể trả lại nút $ trong hook này hay tôi hoàn toàn phải thực hiện một nút_load? Tôi thực sự nghĩ rằng tôi đã có đối tượng nút được truyền trực tiếp thông qua hook_node_update ....
tổng quan

Ok vì vậy tôi đã cập nhật mã theo khuyến nghị của bạn - đó là trong phần thân ban đầu. Vấn đề: Vòng lặp vô tận trong đó trang không tải và cả mysql và apache bắt đầu tải lên 85% trên cpu. Chắc chắn có một số vòng lặp đang diễn ra ở đây. Bất cứ một đề nghị nào khác?
tổng điều tra

Tôi không thể nói cho bạn biết chuyện gì đang xảy ra. Nhưng có lẽ bạn thử một lần để chỉ tải nút, nhập một cái gì đó vào trường và lưu nó bằng node_save (). Hoặc chỉ cần tải, in một cái gì đó (sử dụng watchdog hoặc dpm () và lưu lại để xem nó có hoạt động không
Lance

Vấn đề bắt nguồn từ việc đã lưu nút trước khi lưu nó dẫn đến một vòng lặp đệ quy. Lựa chọn móc kém và xây dựng kém
tổng quan 23/212

1

Một cải tiến của giải pháp Lance ở trên, tránh việc lưu toàn bộ nút khi chỉ một vài giá trị trường được sửa đổi:

$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));

Điều này cũng có thể hữu ích để tránh tác dụng phụ của node_save() .

Nguồn: Lưu các trường của nút mà không lưu chính nút đó

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

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.