Score:0

$node->save() ล้มเหลวเมื่อทำงานใน post_update

ธง us

ฉันมีฟังก์ชั่น hook_post_update อย่างง่ายซึ่งล้มเหลวโดยมีข้อผิดพลาดดังต่อไปนี้:

[ประกาศ] เริ่มการอัปเดตแล้ว: ssc_custom_post_update_9001

[ข้อผิดพลาด] LogicException: บริบทการแสดงผลว่างเปล่า เนื่องจากมีการเรียกใช้การเรนเดอร์ () นอกการเรียกเรนเดอร์รูท () หรือเรนเดอร์เพลน () ใช้ renderPlain()/renderRoot() หรือ #lazy_builder/#pre_render แทน ใน Drupal\Core\Render\Renderer->doRender() (บรรทัดที่ 244 ของ E:\www\myssc\html\core\lib\Drupal\Core\Render\Renderer.php) [ข้อผิดพลาด] บริบทการแสดงผลว่างเปล่า เนื่องจากมีการเรียกใช้การเรนเดอร์ () นอกการเรียกเรนเดอร์รูท () หรือเรนเดอร์เพลน () ใช้ renderPlain()/renderRoot() หรือ #lazy_builder/#pre_render แทน [ข้อผิดพลาด] การอัปเดตล้มเหลว: ssc_custom_post_update_9001

ใน ProcessBase.php บรรทัดที่ 171:

ไม่สามารถถอดรหัสเอาต์พุตเป็น JSON: ข้อผิดพลาดทางไวยากรณ์

[ข้อผิดพลาด] [โหนด] [2022-03-12T04:58:35] LogicException: บริบทการแสดงผล ว่างเปล่า เนื่องจากมีการเรียก render() ภายนอกของ renderRoot() หรือ การเรียก renderPlain() ใช้ renderPlain()/renderRoot() หรือ #lazy_builder/#pre_re แทน ใน Drupal\Core\Render\Renderer->doRender() (บรรทัดที่ 244 ของ E:\www\myssc\html\core\lib\Drupal\C ore\Render\Renderer.php) | uid: 0 | คำขอ-uri: http://default/ | อ้างอิง: | ไอพี: 127.0.0.1 | ลิงค์:
{ "0": { "ssc_custom": { "9001": { "#ยกเลิก": { "สำเร็จ": เท็จ "แบบสอบถาม": "Drupal\Core\Entity\EntityStorageException: บริบท Ren der ว่างเปล่า เนื่องจากมีการเรียก render() นอก a การเรียก renderRoot() หรือ renderPlain() ใช้ re nderPlain()/renderRoot() หรือ #lazy_builder/#pre_render แทน ใน Drupal\Core\Ent
ity\Sql\SqlContentEntityStorage->save() (บรรทัดที่ 810 ของ E:\www\myssc\html\core\lib\Drupal\Core\Entity\Sql\SqlContentEntityStorage.php)" } } }, "#ยกเลิก": [ "ssc_custom_post_update_9001" ] }, "drush_batch_process_finished": จริง }

ฉันได้ถอดรหัสออกจนเหลือน้อยที่สุด:

ใช้ Drupal\Core\Entity\EntityStorageInterface;
ใช้ Drupal\Core\Entity\EntityTypeManagerInterface;
ใช้ Drupal\node\NodeInterface;

ฟังก์ชัน ssc_custom_post_update_9001(&$แซนด์บ็อกซ์) {
  /** @var \Drupal\node\NodeStorageInterface $node_storage */
  $node_storage = \Drupal::entityTypeManager()->getStorage('โหนด');

  // จำนวนเอนทิตีที่ต้องประมวลผลต่อชุด
  $จำกัด = 5;

  $node_ids = $node_storage->getQuery()
    -> การเข้าถึงตรวจสอบ (เท็จ)
    ->เงื่อนไข ('ประเภท', 'บทความ')
    ->ช่วง(0, $จำกัด)
    ->ดำเนินการ ();
  // โหลดเอนทิตี
  $nodes = $node_storage->loadMultiple($node_ids);

  /** @var \Drupal\node\NodeInterface $node */
  foreach ($ โหนดเป็น $ โหนด) {
    $node->setNewRevision();
    $node->save();
  }

  $แซนด์บ็อกซ์['#เสร็จสิ้น'] = 1;

}

ถ้าฉันเรียกใช้รหัสเดียวกันโดยตรง (ไม่ใช่จาก drush updb) มันก็ทำงานได้ดี ทำงานจากเมนูผู้ดูแลระบบ "เรียกใช้การอัปเดต"; มันก็ล้มเหลวเช่นกัน (ดังนั้นจึงไม่ใช่ปัญหาที่น่าเบื่อ)

แสดงความคิดเห็น $node->save() และข้อผิดพลาดไม่เกิดขึ้น

sonfd avatar
in flag
สิ่งนี้จะเกิดขึ้นหากคุณโหลดและบันทึกเนื้อหาประเภทอื่นหรือไม่
leymannx avatar
ne flag
นี่ไม่ใช่วิธีการทำงานของแบทช์ การอัปเดตเนื้อหาควรเกิดขึ้นใน `hook_deploy_N` ที่ทำงานหลังจากนำเข้าการกำหนดค่าเมื่อดำเนินการ `drush deploy`
4uk4 avatar
cn flag
หากเกิดข้อผิดพลาดในฟังก์ชัน Drupal ที่ใช้ในหลายๆ ที่ คุณต้องตรวจสอบ call stack จากตำแหน่งที่เรียกใช้ นี่อาจชี้ไปที่โมดูลที่เชื่อมต่อกับกระบวนการบันทึกโหนด
liquidcms avatar
us flag
อืม น่าแปลกที่ฉันไม่ได้รับการแจ้งเตือนจาก Drupal Answers อีกต่อไป.. @sonfd ใช่ เนื้อหาทุกประเภทleymannx ไม่แน่ใจว่า hook_deploy คืออะไร จะดู; แต่ hook_post_update ระบุว่ามีไว้สำหรับงานเช่นนี้โดยเฉพาะเมื่อคุณต้องการอัปเดตเนื้อหาของไซต์และตัวอย่างแม้กระทั่งแสดงโดยใช้แบตช์และการบันทึกโหนด: https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Extension %21module.api.php/function/hook_post_update_NAME/9.0.x
liquidcms avatar
us flag
@4uk4 ใช่ นั่นคือแผนต่อไปของฉัน.. ตรวจแก้จุดบกพร่องในคอร์เพื่อดูว่าสิ่งนี้ล้มเหลวตรงไหน และดูว่าฉันสามารถบอกได้ว่าโมดูลใดเป็นสาเหตุของสิ่งนี้ ฉันได้ลบรหัสที่กำหนดเองทั้งหมดของฉัน (ซึ่งมีโหนดบันทึก) และไม่ใช่ปัญหา แปลกที่ไม่มีวิธีการเรียกใช้การอัปเดตที่สามารถหลีกเลี่ยงปัญหานี้ได้เนื่องจากดูเหมือนจะไร้สาระที่จะแก้ไขโมดูลที่สนับสนุนโหล (ใช่แล้วอาจจะไม่มากขนาดนั้น) เพื่อทำการอัปเดตเนื้อหาอย่างง่าย อีกทางหนึ่งฉันสามารถให้ปุ่มแก่ลูกค้าหลังจากอัปเกรดไซต์แล้ว แต่แน่นอนว่าเป็นการถดถอยจาก D7 ที่ฉันไม่สามารถให้สคริปต์การปรับใช้ทำการอัปเดตได้
liquidcms avatar
us flag
@leymannz ไม่มีสิ่งที่เรียกว่า hook_deploy - อาจมีบางสิ่งที่เพิ่มเข้ามาโดยโมดูล contrib? ปรับใช้บางที?
cn flag
มันคือตะขอแขวน @liquidcms
Score:2
ธง cn

คุณสามารถทำซ้ำข้อผิดพลาดด้วย Drush:

# ดรัช php.ini

>>> $build = ['#markup' => 'TEST'];
=> [
     "#markup" => "ทดสอบ",
   ]

>>> $rendered = \Drupal::service('renderer')->render($build);
LogicException พร้อมข้อความ 'บริบท Render ว่างเปล่า เนื่องจากมีการเรียกการเรนเดอร์ () นอกการเรียกการเรนเดอร์รูท () หรือเรนเดอร์เพลน () ใช้ renderPlain()/renderRoot() หรือ #lazy_builder/#pre_render แทน'

>>> $rendered = \Drupal::service('renderer')->renderPlain($build);
=> Drupal\Core\Render\มาร์กอัป {#4668
     มาร์กอัป: "ทดสอบ",
   }

เนื่องจากข้อความแสดงข้อผิดพลาดระบุว่าโมดูลที่เชื่อมต่อกับกระบวนการบันทึกโหนดควรใช้ renderPlain() แทน พวกเขาไม่ควรถือว่าโหนดได้รับการบันทึกเสมอในบริบทการแสดงผลของหน้า Drupal ที่มีธีม

ตัวอย่างโค้ดสำหรับการแสดงมุมมองแยก:

$build = $view->buildRenderable();
$rendered = \Drupal::service('renderer')->renderPlain($build);
liquidcms avatar
us flag
กลายเป็นว่ารหัสที่กำหนดเองของฉันทำให้เกิดปัญหา ฉันมีรหัสที่ทำงานบนโหนดบันทึก / บันทึกล่วงหน้าซึ่งพยายามรับค่าจากมุมมองและใช้ advancedRender() ซึ่งฉันคิดว่าเป็นสาเหตุของปัญหานี้ น่าผิดหวังที่รหัสของฉันทำงานตามปกติเมื่อโหนดได้รับการบันทึกตามปกติ แต่ใน post_update ฉันถูกบล็อกไม่ให้ทำเช่นนี้ ง่ายพอที่จะหลีกเลี่ยงได้เนื่องจากฟังก์ชันเหล่านี้ไม่จำเป็นต้องเรียกใช้ระหว่างการอัปเดตนี้ แต่แปลกที่ฉันต้องทำแฮ็คนี้
4uk4 avatar
cn flag
หากฟังก์ชัน render() ไม่ได้อยู่ในการควบคุมของคุณ เช่นที่นี่ใน View คุณสามารถใส่โค้ดใน RenderContext ของคุณเองและละทิ้งข้อมูลเมตาที่ฟองขึ้น Drupal ทำสิ่งนี้เมื่อแสดงเมล ดู https://drupal.stackexchange.com/questions/245715/how-to-get-cache-metadata-from-nested-render-array-when-returning-response
liquidcms avatar
us flag
ขอบคุณสำหรับคำแนะนำ .. น่ารู้ แม้ว่าจะมีงานมากมายในการคัดลอกฟิลด์ไปยังฟิลด์ใหม่เป็น 1 ครั้ง สำหรับตอนนี้ ฉันเพียงแค่ตั้งค่า var แบบคงที่ในสคริปต์การอัปเดต จากนั้นใช้สิ่งนั้นเพื่อละเว้นฟังก์ชันบันทึก/บันทึกล่วงหน้า เนื่องจากไม่จำเป็นต้องเรียกใช้เมื่อการอัปเดตนี้ทำงาน
4uk4 avatar
cn flag
ตกลง แต่วิธีนี้ไม่ได้แก้ปัญหาการรั่วไหลของข้อมูลเมตาในบริบทการแสดงผลที่ไม่รู้จัก การรันการเรนเดอร์ () หรือโค้ดที่มีเรนเดอร์ () ควรทำให้ข้อมูลเมตาเป็นฟองก็ต่อเมื่อคุณสามารถตรวจสอบให้แน่ใจว่าบริบทการเรนเดอร์เป็นของเนื้อหาที่เรนเดอร์ ส่วนใหญ่แล้วนี่คือบริบทการแสดงผลของหน้าเมื่อสร้างองค์ประกอบของหน้า

โพสต์คำตอบ

คนส่วนใหญ่ไม่เข้าใจว่าการถามคำถามมากมายจะปลดล็อกการเรียนรู้และปรับปรุงความสัมพันธ์ระหว่างบุคคล ตัวอย่างเช่น ในการศึกษาของ Alison แม้ว่าผู้คนจะจำได้อย่างแม่นยำว่ามีคำถามกี่ข้อที่ถูกถามในการสนทนา แต่พวกเขาไม่เข้าใจความเชื่อมโยงระหว่างคำถามและความชอบ จากการศึกษาทั้ง 4 เรื่องที่ผู้เข้าร่วมมีส่วนร่วมในการสนทนาด้วยตนเองหรืออ่านบันทึกการสนทนาของผู้อื่น ผู้คนมักไม่ตระหนักว่าการถามคำถามจะมีอิทธิพลหรือมีอิทธิพลต่อระดับมิตรภาพระหว่างผู้สนทนา