Jak programowo uzyskać identyfikator NID bieżącego węzła


26

Zastanawiałem się nad tym starym wątkiem na drupal.org i to po prostu sprawia, że ​​kręci mi się w głowie. Zjeżdżasz ścieżką i próbujesz oddzielić NID od niej? Musi być lepszy sposób.

I takie rozwiązania

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

nie działają w moim module niestandardowym (chociaż powiedziano mi, że działają w szablonach?). Brak błędu lub cokolwiek innego, po prostu $nodetworzy on NULLwartość.

Wydaje się, że musi istnieć coś naprawdę oczywistego, czego mi brakuje.

Jak więc uzyskać identyfikator NID bieżącego węzła bez szablonu, postępując zgodnie z najlepszymi praktykami i budując dość solidny moduł?

Odpowiedzi:


50

Zakładając, że kod działa na stronie węzła, metody, które widzę najczęściej używane w modułach core / contrib, używają menu_get_object()albo arg():

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

lub

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);
}

Ja osobiście wolę pierwszą metodę (nawet jeśli przypisanie warunku nie jest uważane przez niektórych za dobry pomysł), ale obie są całkowicie poprawne.


1
@Letharion Tak, czuję się trochę winny za każdym razem, gdy to robię;)
Clive

1
@beth Z jakiej funkcji ją wywołujesz? I czy jest to zdecydowanie strona węzła, na którą ją wywołujesz?
Clive

1
@ bet W 100% będą działać z włączonym aliasingiem ścieżek. Ścieżka aliasing nie ma nic wspólnego ze ścieżką routera z menu, które jest node/1, node/2itd. Jeśli nadal występują problemy Może warto wpis kolejne pytanie z dokładnym kodem, którego używasz, i dostarczyć trochę kontekstu. Wtedy moglibyśmy być w stanie wskazać, gdzie dzieje się problem
Clive

1
Rozwiązanie $nid = ($node = menu_get_object()) ? $node->nid : NULL;
jednoliniowe

3
@sheldonkreger Węzeł jest już załadowany przez ten punkt menu_get_object()(lub nawet node_load()) pobiera go ze statycznej pamięci podręcznej. Nawet jeśli wywołasz go wcześnie, nadal będzie on ładowany przez moduł podstawowy później w kompilacji strony (ponieważ jest to strona węzła), w takim przypadku po prostu ocieplisz statyczną pamięć podręczną dla następnego procesu
Clive

5

Najłatwiejszym sposobem na to w Drupal 8, ponieważ arg () już nie działa:

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

Zmień zapis


2
Działa to również w Drupal 7. Jeśli jednak znajdujesz się na stronie, która nie jest węzłem, takim jak admin / structure / blocks, otrzymasz nieprawidłową wartość (w tym przypadku „strukturę”). Po prostu sprawdź, czy path_args [1] jest liczbą całkowitą i prawdopodobnie nic ci nie jest.
sheldonkreger

Prawdopodobnie będziesz chciał użyć arg (1) zamiast eksplodować, ponieważ już to zrobił dla Ciebie: api.drupal.org/api/drupal/includes%21bootstrap.inc/function/arg/…
RobLoach

1
@RobLoach ale arg () nie istnieje w D8
Pouya Sanooei

4

arg(0)zwraca „węzeł” i arg(1)zwraca węzeł nid.

if (arg(0) == 'node' && is_numeric(arg(1))) {
  $nid = arg(1);
}

1

Ten link pomógł mi: http://www.webomelette.com/node-id-nid-url-path-alias - Idź do zawartości i filtruj przestarzałe, aby znaleźć treść, dla której chcesz zobaczyć identyfikator węzła i najechać myszą na Edycja połączyć. Spójrz w dół, aby zobaczyć hiperłącze, które wyświetla Twoja przeglądarka, jeśli klikniesz Edytuj.


Cześć Ana, witamy w Drupal Answers. Twoja odpowiedź jest dobra (i głosowałem za nią), jednak pytanie brzmi: jak programowo uzyskać nid, ponieważ zawiera on „z modułu” w tytule.
Darvanen

1

Druga metoda w obecnie akceptowanej odpowiedzi jest najczystsza w D7. Pierwsza odpowiedź:

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

jest tylko wizualnie czystszy. W rzeczywistości menu_get_object()wywołuje sporo kodu i może prowadzić do nieprzewidzianych błędów. Używałem go wewnątrz hook_node_grants()funkcji i napotkałem błąd krytyczny PHP:

Osiągnięto maksymalny poziom zagnieżdżenia funkcji „256”, przerywanie!

Wyjaśnienie na stronie /drupal//a/69232/9158

Nieskończona pętla, którą zauważasz, jest spowodowana faktem, menu_get_object()że Drupal sprawdza, czy aktualnie zalogowany użytkownik ma dostęp do węzła, co powoduje hook_node_grants()ponowne wywołanie implementacji , która wywołuje menu_get_object(), co powoduje hook_node_grants()ponowne wywołanie implementacji , który...

Zostało to rozwiązane za pomocą drugiej metody:

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

Inna opcja, w 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;
  }
}

Jeśli planujesz używać funkcji poza modułem, nie używaj początkowego _ na początku nazwy funkcji.


1
To to samo, ale z drogim wezwaniem do nadzoru na wszystkich ścieżkach, które nie są węzłami.
beth

Lubię wiedzieć, czy mój kod nieoczekiwanie zawiedzie. Nie chciałbym, aby ten kod był wykonywany na urządzeniach innych niż węzły, watchdog pokaże mi, gdzie to się dzieje, więc mogę to naprawić. W przeciwnym razie nie będę mieć śladu, że ten kod działa bez powodu (na urządzeniach innych niż węzły). W przeciwnym razie jest to to samo co wspomniana powyżej metoda D8.
sheldonkreger

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

Czy możesz dodać do odpowiedzi kilka „dlaczego” i „jak”? Odpowiedź tylko z kodem może działać, ale nie pomaga zrozumieć własnych błędów.
Mołot

Najpierw sprawdza, czy węzeł jest zdefiniowany przed wykonaniem.
cptstarling
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.