Как программно получить 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];

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

Pouya Sanooei
источник
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
4

arg(0)возвращает «узел» и arg(1)возвращает нод.

if (arg(0) == 'node' && is_numeric(arg(1))) {
  $nid = arg(1);
}
Себастьян Гикель
источник
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');
user373707
источник
Лучше обернуть вывод, как показано в 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;
  }
}

Если вы планируете использовать функцию за пределами вашего модуля, не используйте начальный _ в начале имени функции.

sheldonkreger
источник
1
Это то же самое, но с дорогим сторожевым вызовом на всех путях, которые не являются узлами.
Beth
Мне нравится знать, что мой код неожиданно дает сбой. Я бы не хотел, чтобы этот код выполнялся не на узлах, сторожевой таймер покажет мне, где это происходит, чтобы я мог это исправить. В противном случае я не буду отслеживать, что этот код выполняется без причины (не на узлах). В остальном он такой же, как метод D8, упомянутый выше.
Шелдонкрегер
-1
<?php
if (isset($node->nid) && count($node->nid) > 0){
  $mynodeid = $node->nid;
}
?>
cptstarling
источник
Не могли бы вы добавить некоторые «почему» и «как» к вашему ответу? Ответ только на код может сработать, но вряд ли поможет понять свои ошибки.
Молот
Сначала проверяется, определен ли узел перед выполнением.
cptstarling