Как программно получить NID текущего узла


26

Я посмотрел на эту старую ветку на drupal.org, и это как бы заставляет мою голову крутиться. Срывать путь и пытаться разобрать NID изнутри? Там должен быть лучший путь.

И такие решения, как

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

не работают в моем пользовательском модуле (хотя мне сказали, что они работают в шаблонах?). Нет ошибок или чего-то еще, он просто $nodeсоздается со NULLзначением.

Такое ощущение, что должно быть что-то действительно очевидное, что я скучаю.

Итак, как получить NID текущего узла без шаблона, следуя рекомендациям и создавая достаточно надежный модуль?

Ответы:


50

Предполагая, что ваш код выполняется для страницы узла, методы, которые я вижу чаще всего используемые в модулях core / contrib, используют 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 Да, я чувствую себя немного виноватым каждый раз, когда я делаю это;)
Клайв

1
@beth Из какой функции ты это вызываешь? И это определенно страница узла, на которую вы ее вызываете?
Клайв

1
@beth Они на 100% будут работать с включенным псевдонимом пути. Путь сглаживание не имеет ничего общего с маршрутизатором пути из пункта меню, которое node/1, и node/2т.д. Если вы все еще возникают проблемы , что может быть стоит размещение еще один вопрос с точным кодом , который вы используете, и обеспечить немного контекста. Тогда мы сможем точно определить, где происходит проблема
Клайв

1
Решение с одной линией$nid = ($node = menu_get_object()) ? $node->nid : NULL;
timofey.com

3
@sheldonkreger Узел, уже загруженный к этому моменту menu_get_object()(или даже node_load()), просто получает его из статического кэша. Даже если вы вызываете его на раннем этапе, он все равно будет загружен основным модулем позже в сборке страницы (поскольку это страница узла), в этом случае вы просто нагреваете статический кеш для следующего процесса
Клайв

5

Самый простой способ сделать это в Drupal 8, так как arg () больше не работает:

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

Изменить запись


2
Это также работает в Drupal 7. Однако, если вы находитесь на странице, которая не является узлом, например, admin / Structure / Blocks, вы получите недопустимое значение (в данном случае, «структура»). Просто проверьте, является ли path_args [1] целым числом, и вы, вероятно, в порядке.
Шелдонкрегер

Вы, вероятно, захотите использовать 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 - Перейти к содержанию и отфильтровать вниз, чтобы найти содержимое, для которого вы хотите видеть идентификатор узла, и навести курсор на него. ссылка. Посмотрите вниз, чтобы увидеть гиперссылку, которую ваш браузер сообщает, что будет следовать, если вы нажмете на Изменить.


Привет, Ана, добро пожаловать в Drupal. Ваш ответ хороший (и я проголосовал за него), однако вопрос заключается в том, как получить nid программным путем, так как в заголовке содержится «из модуля».
Дарванен

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

В D8:

$node = \Drupal::routeMatch()->getParameter('node');

Лучше обернуть вывод, как показано в drupal.stackexchange.com/a/145826/15055 . И также стоит отметить, что это не будет работать на страницах предварительного просмотра узла и страницах ревизии узла.
leymannx

-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
Это то же самое, но с дорогим сторожевым вызовом на всех путях, которые не являются узлами.
Beth

Мне нравится знать, что мой код неожиданно дает сбой. Я бы не хотел, чтобы этот код выполнялся не на узлах, сторожевой таймер покажет мне, где это происходит, чтобы я мог это исправить. В противном случае я не буду отслеживать, что этот код выполняется без причины (не на узлах). В остальном он такой же, как метод D8, упомянутый выше.
Шелдонкрегер

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

Не могли бы вы добавить некоторые «почему» и «как» к вашему ответу? Ответ только на код может сработать, но вряд ли поможет понять свои ошибки.
Молот

Сначала проверяется, определен ли узел перед выполнением.
cptstarling
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.