Як програмно отримати 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. Однак, якщо ви знаходитесь на сторінці, яка не є вузлом, наприклад, адміністратор / структура / блоки, ви отримаєте недійсне значення (у цьому випадку - "структура"). Просто перевірте, чи є path_args [1] цілим числом, і ви, напевно, добре.
sheldonkreger

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


Привіт, Ана, ласкаво просимо до друпальських відповідей. Ваша відповідь хороша (і я проголосував за спробу), однак питання полягає в тому, як програмно отримати 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

Ще один варіант у 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, згаданий вище.
sheldonkreger

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

Не могли б ви додати до своєї відповіді кілька "whys" та "hows"? Відповідь, кодовий лише для коду, може спрацювати, але навряд чи допоможе зрозуміти помилки.
Молот

Він спочатку перевіряє, чи визначений вузол перед виконанням.
cptstarling
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.