7

我正在尝试创建一个节点(B 类型)并使用 node_save() 方法将其分配给 A 类型节点的 CCK 节点引用字段。

$node_type_A = node_load($some_nid);
$node_type_A->field_type_B_node_ref[]['nid'] = $node_type_B_nid;

$node_type_A = node_submit($node_type_A);
node_save($node_type_A);

结果,将创建一个新的 B 类型节点,但不会将引用分配给 A 类型节点。任何帮助,将不胜感激。

4

5 回答 5

6

GApple是对的,格式是正确的,但是您可能需要关心一些事情。

Delta值
首先要知道最新的节点引用的delta$node_type_A值,这个delta实际上是一个部分索引,当与 的vid字段结合时$node_type_A,它们成为数据库中节点引用表的索引。换句话说,它是$node_type_B在 中引用的计数$node_type_A,好吗?

GApple 又是对的,您必须准确说明在何处添加新参考。当您获得该delta值时,您可以准确地说出在哪里附加(delta+1)新参考。这里是:

function get_current_delta($node_vid){
    return db_result(db_query("SELECT delta FROM {content_field_type_A_node_ref}
                               WHERE vid = '%d'
                               ORDER BY delta DESC
                               LIMIT 1", $node_vid));
}

添加新参考
我们得到了delta!所以我们可以将新$node_type_B节点附加到我们的$node_type_A节点:

// Loading type_A node.
$node_type_A = node_load($some_nid);

// Getting current delta value.
$current_delta = get_current_delta($node_type_A->vid);

// "Appending" a node reference based on delta. 
$node_type_A->field_type_B_node_ref += array($current_delta + 1 => array('nid' => $node_type_B_nid));

重新保存更新的节点
可选调用node_submit()以填充节点对象中的一些基本字段并使用node_save(). 毕竟,您需要调用content_insert()以使节点与其 CCK 字段一起完全保存:

// Resaving the updated node.
$node_type_A = node_submit($node_type_A);
node_save($node_type_A);
content_insert($node_type_A);

刷新内容缓存
可能是最重要的部分,这让我死了几天。CCK 在数据库中有一个名为cache_content (看看它的结构)的缓存表,在重新保存更新的节点后,您会注意到$node_type_A即使表已更新,主题输出中也没有任何变化。我们必须从该内容缓存表中删除一条记录,这将强制 Drupal 显示数据的最新快照。您可以将以下内容定义为函数:

db_query("DELETE FROM {cache_content} WHERE cid = '%s'", 'content:' . $node_type_A->nid . ':' . $node_type_A->vid);

希望能帮助到你 ;)

于 2010-05-05T14:52:14.777 回答
4

我刚刚检查了我自己的一个模块,它对对象格式做了类似的事情, $node_type_A->field_type_B_node_ref[]['nid']应该是正确的。

要检查的一件事是,当您加载节点时,CCK 可能会使用空值预先填充节点引用数组。如果您已将该字段配置为仅允许一个值,则通过使用数组附加运算符 ( field_type_B_node_ref[]),它将创建第二个将被忽略的条目 ( field_type_B_node_ref[1]),而不是覆盖现有值 ( field_type_B_node_ref[0])。如果可能,请尝试显式指定数组键。

于 2010-04-27T19:46:53.473 回答
3

很棒的帖子,但有一个更正:不要通过手动查询数据库来刷新缓存条目。如果有人使用 memcache 或任何其他外部缓存,它将失败。

cache_clear_all()是你清除的朋友。

建议的代码,直接来自 CCK 模块:

cache_clear_all('content:'. $node_type_A->nid .':'. $node_type_A->vid, content_cache_tablename());
于 2012-03-31T04:54:35.180 回答
0

我将 CCK 存储节点引用显示为$node->field_node_reference[0]['items'][0]['nid'],而不是 $node->field_node_reference[0]['nid']。你试过模仿吗?

于 2010-04-27T17:51:03.020 回答
0

“刷新内容缓存”这对我有用,特别是如果您从 node_load() 获取数据

于 2010-05-24T01:39:14.807 回答