如何以编程方式获取当前节点的NID


26

我已经仔细研究了drupal.org上的这个旧线程,这只是使我的头旋转了一下。拉下路径并尝试从其中解析出NID?一定有更好的方法。

和类似的解决方案

global $node;
$nid = $node->nid;

不能在我的自定义模块中工作(尽管我被告知它们可以在模板中工作?)。没有错误或任何东西,它只是实例化$node一个NULL值。

感觉好像我确实缺少某些明显的东西。

因此,在遵循最佳实践并构建合理可靠的模块的同时,如何在没有模板的情况下获取当前节点的NID?

Answers:


50

假设您的代码正在为节点页面运行,那么我在核心/贡献模块中最常用的方法就是使用menu_get_object()arg()

if ($node = menu_get_object()) {
  // Get the nid
  $nid = $node->nid;
}

要么

if (arg(0) == 'node' && is_numeric(arg(1))) {
  // Get the nid
  $nid = arg(1);

  // Load the node if you need to
  $node = node_load($nid);
}

我个人更喜欢第一种方法(即使某些人认为条件分配不是一个好主意),但两者都是完全有效的。


1
@Letharion是的,每次我都感到有点内;;)
Clive

1
@beth您从哪个函数调用它?肯定是您正在调用它的节点页面吗?
克莱夫(Clive)

1
@beth他们100%将启用路径别名。路径别名与菜单项的路由器路径无关,该路径node/1node/2等等。如果仍然遇到问题,可能值得用您使用的确切代码发布另一个问题,并提供一些上下文信息。然后,我们也许可以查明问题出在哪里
克莱夫(Clive

1
单线解决方案$nid = ($node = menu_get_object()) ? $node->nid : NULL;
timofey.com 2013年

3
@sheldonkreger到该点已经加载的节点,menu_get_object()(或什至node_load())只是从静态缓存中获取它。即使您早点调用它,它也仍会在页面构建中稍后由核心模块加载(因为这是一个节点页面),在这种情况下,您只需为下一过程预热静态缓存
克莱夫(Clive)

5

由于arg()不再起作用,因此在Drupal 8中最简单的方法是:

$path_args = explode('/', current_path());
print $path_args[1];

变更记录


2
这在Drupal 7中也适用。但是,如果您位于不是节点的页面上,例如admin / structure / blocks,那么您将收到一个无效值(在这种情况下为'structure')。只需检查一下path_args [1]是否为整数,就可以了。
sheldonkreger 2014年

您可能想使用arg(1)而不是爆炸,因为它已经为您完成了:api.drupal.org/api/drupal/includes%21bootstrap.inc/function/arg/…–
RobLoach

1
@RobLoach但arg()在D8中不存在
Pouya Sanooei


1

此链接对我有帮助:http : //www.webomelette.com/node-id-nid-url-path-alias-转到“内容”,然后向下过滤以查找要查看其节点ID并将其悬停在“编辑”上的内容链接。向下看,如果您单击“编辑”,浏览器将指示您将跟随超链接。


嗨,安娜,欢迎来到Drupal Answers。您的回答很好(我已为尝试投了赞成票),但是问题是询问如何以编程方式获取nid,因为它的标题中包含“来自模块”。
Darvanen 2014年

1

当前接受的答案中的第二种方法是D7中最干净的方法。第一个答案:

if ($node = menu_get_object()) {
  // Get the nid
  $nid = $node->nid;
}

仅在视觉上更清洁。实际上,menu_get_object()正在调用很多代码,并可能导致无法预料的错误。我在hook_node_grants()函数内部使用它,并遇到了PHP致命错误:

达到最大功能嵌套级别“ 256”,正在中止!

可以在/drupal//a/69232/9158中找到说明

您注意到的无限循环是由以下事实引起的,该事实 menu_get_object()导致Drupal验证当前登录的用户是否有权访问该节点,这导致您的实现 hook_node_grants()再次被调用,该调用menu_get_object()导致您的实现hook_node_grants()再次被调用。 , 哪一个...

这是通过使用第二种方法解决的:

if (arg(0) == 'node' && is_numeric(arg(1))) {
  // Get the nid
  $nid = arg(1);

  // Load the node if you need to
  $node = node_load($nid);
}


-1

D7中的另一种选择:

function _my_module_get_nid() {
  $path_args = explode('/', current_path());
  //$nid = $path_args[1];
  if(is_int($path_args)) {
    return($path_args[1]);
  }
  // Log that we failed to load a NID.
  else {
    watchdog('my_module', 'Unable to gather NID at: ' . current_path(),  WATCHDOG_WARNING, NULL);
  return FALSE;
  }
}

如果您打算在模块外部使用该函数,请不要在函数名称的开头使用_。


1
这是同一件事,但是在不是节点的所有路径上都有一个昂贵的看门狗调用。
2014年

我想知道我的代码是否意外失败。我不想在非节点上执行此代码,看门狗会告诉我发生了什么,所以我可以修复它。否则,我将无法跟踪该代码无缘无故地运行(在非节点上)。否则,它与上述D8方法相同。
sheldonkreger

-1
<?php
if (isset($node->nid) && count($node->nid) > 0){
  $mynodeid = $node->nid;
}
?>

您能在答案中添加一些“为什么”和“方法”吗?仅代码的答案可能有用,但是很难理解一个人的错误。
Mołot

在执行之前,它首先检查节点是否已定义。
cptstarling
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.