วิธีรับ NID ของโหนดปัจจุบันโดยทางโปรแกรม


26

ฉันได้อ่านหัวข้อเก่า ๆ นี้ที่ drupal.orgและมันทำให้หัวฉันหมุนไปรอบ ๆ ดึงเส้นทางลงและพยายามแยก NID ออกจากภายในหรือไม่ จะต้องมีวิธีที่ดีกว่า

และวิธีแก้ปัญหาเช่น

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

ไม่ทำงานในโมดูลที่กำหนดเองของฉัน (แต่ฉันบอกว่าพวกเขาทำงานในแม่แบบได้หรือไม่) ไม่มีข้อผิดพลาดหรืออะไรมันแค่ยกตัวอย่าง$nodeด้วยNULLค่า

มันรู้สึกเหมือนว่าจะต้องมีบางสิ่งบางอย่างที่ชัดเจนว่าฉันหายไป

ดังนั้นคุณจะรับ NID ของโหนดปัจจุบันโดยไม่มีแม่แบบได้อย่างไรในขณะที่ปฏิบัติตามแนวทางปฏิบัติที่ดีที่สุดและสร้างโมดูลที่แข็งแกร่งพอสมควร

คำตอบ:


50

สมมติว่ารหัสของคุณกำลังทำงานสำหรับหน้าโหนดวิธีที่ฉันเห็นใช้บ่อยที่สุดใน core / contrib modules อาจใช้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% จะทำงานเมื่อเปิดใช้งานการใช้ชื่อแทนพา ธ เส้นทาง aliasing มีอะไรจะทำอย่างไรกับเส้นทางที่เราเตอร์ของรายการเมนูซึ่งเป็นnode/1, node/2ฯลฯ หากคุณยังคงมีปัญหาอาจจะมีมูลค่าการโพสต์คำถามอื่นที่มีรหัสตรงกับที่คุณกำลังใช้และให้บิตของบริบท จากนั้นเราอาจสามารถระบุตำแหน่งที่เกิดปัญหาได้
ไคลฟ์

1
โซลูชันบรรทัดเดียว$nid = ($node = menu_get_object()) ? $node->nid : NULL;
timofey.com

3
@sheldonkreger โหนดที่โหลดไปแล้วโดยจุดนั้นmenu_get_object()(หรือแม้กระทั่งnode_load()) เพิ่งได้รับมาจากแคชแบบคงที่ แม้ว่าคุณจะเรียกมันก่อน แต่ก็ยังจะถูกโหลดโดยโมดูลหลักในภายหลังในการสร้างหน้า (เช่นนี้เป็นหน้าโหนด) ในกรณีที่คุณเพิ่งอุ่นแคชแบบคงที่สำหรับกระบวนการถัดไป
Clive

5

วิธีที่ง่ายที่สุดในการทำเช่นนี้ใน Drupal 8 ตั้งแต่ ARG () ไม่ทำงานอีกต่อไป:

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

เปลี่ยนบันทึก


2
สิ่งนี้สามารถใช้งานได้ใน Drupal 7 อย่างไรก็ตามหากคุณอยู่ในหน้าเว็บที่ไม่ใช่โหนดเช่นผู้ดูแลระบบ / โครงสร้าง / บล็อกคุณจะได้รับค่าที่ไม่ถูกต้อง (ในกรณีนี้คือ 'โครงสร้าง') เพียงตรวจสอบเพื่อดูว่า path_args [1] เป็นจำนวนเต็มและคุณน่าจะดี
sheldonkreger

คุณอาจจะต้องการใช้หาเรื่อง (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 - ไปที่เนื้อหาและตัวกรอง downt เพื่อค้นหาเนื้อหาที่คุณต้องการเห็น Node ID สำหรับและโฮเวอร์เหนือ Edit ลิงค์ ดูลงเพื่อดูไฮเปอร์ลิงก์ที่เบราว์เซอร์ของคุณบอกคุณว่ามันจะตามมาหากคุณคลิกที่แก้ไข


สวัสดีอานายินดีต้อนรับสู่ Drupal Answers คำตอบของคุณเป็นสิ่งที่ดี (และฉันลงคะแนนให้เพื่อพยายาม) อย่างไรก็ตามคำถามจะถามวิธีรับ nid แบบเขียนโปรแกรมเนื่องจากประกอบด้วย 'จากโมดูล' ในชื่อเรื่อง
Darvanen

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
นี่คือสิ่งเดียวกัน แต่ด้วยการโทรหาสุนัขเฝ้าบ้านราคาแพงบนเส้นทางทั้งหมดที่ไม่ใช่โหนด

ฉันชอบที่จะรู้ว่ารหัสของฉันล้มเหลวโดยไม่คาดคิด ฉันไม่ต้องการให้โค้ดนี้ถูกประมวลผลบนโหนดที่ไม่ใช่โหนดจ้องจับผิดจะแสดงให้ฉันเห็นว่าเกิดอะไรขึ้นเพื่อที่ฉันจะสามารถแก้ไขได้ มิฉะนั้นฉันจะไม่มีร่องรอยว่ารหัสนี้ทำงานโดยไม่มีเหตุผล (บน non-nodes) มิฉะนั้นมันก็เหมือนกับวิธี D8 ที่กล่าวถึงข้างต้น
sheldonkreger

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

คุณช่วยเพิ่มคำว่า "whys" และ "hows" ลงในคำตอบของคุณได้ไหมคำตอบที่ใช้รหัสเท่านั้นอาจใช้ได้ แต่แทบจะไม่ช่วยให้เข้าใจข้อผิดพลาด
Mołot

ก่อนอื่นจะตรวจสอบว่ามีการกำหนดโหนดก่อนที่จะดำเนินการ
cptstarling
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.