Điểm:0

$node->save() không thành công khi chạy trong post_update

lá cờ us

Tôi có một hàm hook_post_update đơn giản không thành công với lỗi sau:

[thông báo] Cập nhật bắt đầu: ssc_custom_post_update_9001

[lỗi] LogicException: Bối cảnh kết xuất trống, vì render() được gọi bên ngoài lệnh gọi renderRoot() hoặc renderPlain(). Sử dụng thay vào đó, renderPlain()/renderRoot() hoặc #lazy_builder/#pre_render. Trong Drupal\Core\Render\Renderer->doRender() (dòng 244 của E:\www\myssc\html\core\lib\Drupal\Core\Render\Renderer.php). [lỗi] Bối cảnh kết xuất trống, vì kết xuất() được gọi bên ngoài lệnh gọi renderRoot() hoặc renderPlain(). Sử dụng thay vào đó, renderPlain()/renderRoot() hoặc #lazy_builder/#pre_render. [lỗi] Cập nhật không thành công: ssc_custom_post_update_9001

Trong ProcessBase.php dòng 171:

Không thể giải mã đầu ra thành JSON: Lỗi cú pháp

[ERROR] [node] [2022-03-12T04:58:35] LogicException: Kết xuất ngữ cảnh trống, vì render() được gọi bên ngoài renderRoot() hoặc renderPlain() cuộc gọi. Sử dụng renderPlain()/renderRoot() hoặc #lazy_builder/#pre_re tìm hiểu thay thế. trong Drupal\Core\Render\Renderer->doRender() (dòng 244 của E:\www\myssc\html\core\lib\Drupal\C ore\Render\Renderer.php). | uid: 0 | yêu cầu-uri: http://default/ | tham khảo: | IP: 127.0.0.1 | liên kết:
{ "0": { "ssc_custom": { "9001": { "#Huỷ bỏ": { "thành công": sai, "truy vấn": "Drupal\Core\Entity\EntityStorageException: Ren der context trống, vì render() được gọi bên ngoài lệnh gọi renderRoot() hoặc renderPlain(). Sử dụng lại nderPlain()/renderRoot() hoặc #lazy_builder/#pre_render để thay thế. trong Drupal\Core\Ent
ity\Sql\SqlContentEntityStorage->save() (dòng 810 của E:\www\myssc\html\core\lib\Drupal\Core\Entity\Sql\SqlContentEntityStorage.php)." } } }, "#Huỷ bỏ": [ "ssc_custom_post_update_9001" ] }, "drush_batch_process_finished": true }

Tôi đã loại bỏ mã xuống mức tối thiểu:

sử dụng Drupal\Core\Entity\EntityStorageInterface;
sử dụng Drupal\Core\Entity\EntityTypeManagerInterface;
sử dụng Drupal\node\NodeInterface;

chức năng ssc_custom_post_update_9001(&$sandbox) {
  /** @var \Drupal\node\NodeStorageInterface $node_storage */
  $node_storage = \Drupal::entityTypeManager()->getStorage('node');

  // Có bao nhiêu thực thể được xử lý mỗi đợt.
  giới hạn $ = 5;

  $node_ids = $node_storage->getQuery()
    -> kiểm tra truy cập (SAI)
    ->điều kiện('loại', 'bài viết')
    -> phạm vi (0, giới hạn $)
    ->thực thi();
  // Tải các thực thể.
  $nodes = $node_storage->loadMultiple($node_ids);

  /** @var \Drupal\node\NodeInterface $node */
  foreach ($nodes là $node) {
    $node->setNewRevision();
    $node->save();
  }

  $sandbox['#finished'] = 1;

}

Nếu tôi chạy trực tiếp cùng một mã (không phải từ drush updb) thì nó sẽ chạy tốt. Chạy từ menu quản trị "Chạy cập nhật"; nó cũng không thành công (vì vậy nó không phải là vấn đề về drush).

Nhận xét $node->save() và lỗi không xảy ra.

sonfd avatar
lá cờ in
Điều này có xảy ra nếu bạn tải và lưu một loại nội dung khác không?
leymannx avatar
lá cờ ne
Đây không phải là cách hàng loạt hoạt động. Cập nhật nội dung sẽ diễn ra trong `hook_deploy_N` chạy sau khi nhập cấu hình khi thực hiện `drush Deploy`.
4uk4 avatar
lá cờ cn
Nếu xảy ra lỗi trong chức năng Drupal được sử dụng ở nhiều nơi khác nhau, bạn phải kiểm tra ngăn xếp cuộc gọi từ nơi nó được gọi. Điều này có thể trỏ đến một mô-đun nối vào quá trình lưu nút.
liquidcms avatar
lá cờ us
Hmm, thật kỳ lạ là tôi không còn nhận được thông báo từ Drupal Answers nữa.. @sonfd, vâng, bất kỳ loại nội dung nào.leymannx, không chắc hook_deploy là gì, sẽ xem qua; nhưng hook_post_update nói rằng nó dành riêng cho các tác vụ như thế này khi bạn cần cập nhật nội dung trang web và các ví dụ thậm chí hiển thị bằng cách sử dụng lưu hàng loạt và nút: https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Extension %21module.api.php/function/hook_post_update_NAME/9.0.x
liquidcms avatar
lá cờ us
@ 4uk4, vâng, đó là kế hoạch tiếp theo của tôi.. gỡ lỗi trong lõi để xem lỗi này ở đâu và xem liệu tôi có thể biết mô-đun nào gây ra lỗi này không. Tôi đã xóa tất cả mã tùy chỉnh của mình (đã lưu nút) và đó không phải là vấn đề. Điều kỳ lạ là không có cách nào để chạy một bản cập nhật có thể bỏ qua vấn đề này vì có vẻ ngớ ngẩn khi phải sửa một tá (có, có thể không nhiều) mô-đun đóng góp để thực hiện cập nhật nội dung đơn giản. Ngoài ra, tôi có thể cung cấp cho khách hàng của mình một nút để nhấn sau khi trang web được nâng cấp; nhưng chắc chắn là hồi quy từ D7 mà tôi không thể cập nhật tập lệnh triển khai của mình.
liquidcms avatar
lá cờ us
@leymannz, không có thứ gọi là hook_deploy - có thể là thứ gì đó được thêm vào bởi mô-đun đóng góp? Triển khai có lẽ?
lá cờ cn
Đó là một cái móc drush @liquidcms
Điểm:2
lá cờ cn

Bạn có thể tạo lại lỗi với Drush:

# drush php

>>> $build = ['#markup' => 'KIỂM TRA'];
=> [
     "#markup" => "KIỂM TRA",
   ]

>>> $rendered = \Drupal::service('renderer')->render($build);
LogicException với thông báo 'Bối cảnh kết xuất trống, vì kết xuất() được gọi bên ngoài lệnh gọi renderRoot() hoặc renderPlain(). Thay vào đó, hãy sử dụng renderPlain()/renderRoot() hoặc #lazy_builder/#pre_render.'

>>> $rendered = \Drupal::service('renderer')->renderPlain($build);
=> Drupal\Core\Render\Markup {#4668
     đánh dấu: "KIỂM TRA",
   }

Vì vậy, như thông báo lỗi cho biết các mô-đun nối vào quá trình lưu nút nên sử dụng renderPlain() thay thế. Họ không nên cho rằng các nút luôn được lưu trong ngữ cảnh hiển thị của trang Drupal theo chủ đề.

Ví dụ về mã để hiển thị chế độ xem riêng lẻ:

$build = $view->buildRenderable();
$rendered = \Drupal::service('renderer')->renderPlain($build);
liquidcms avatar
lá cờ us
Hóa ra đó là mã tùy chỉnh của tôi gây ra sự cố. Tôi có mã chạy trên nút lưu/lưu trước đang cố lấy các giá trị từ Chế độ xem và đang sử dụng advancedRender() mà tôi cho là gây ra sự cố này. Thật thất vọng khi mã của tôi hoạt động như bình thường khi các nút thường được lưu nhưng trong post_update tôi bị chặn thực hiện việc này. Đủ dễ dàng để xử lý vì các chức năng này không cần chạy trong quá trình cập nhật này - nhưng kỳ lạ là tôi sẽ cần thực hiện thao tác hack này.
4uk4 avatar
lá cờ cn
Nếu chức năng render() không nằm trong tầm kiểm soát của bạn, chẳng hạn như ở đây trong Chế độ xem, bạn có thể gửi kèm mã trong RenderContext của riêng mình và loại bỏ siêu dữ liệu nổi lên. Drupal thực hiện điều này chẳng hạn khi hiển thị thư. Xem https://drupal.stackexchange.com/questions/245715/how-to-get-cache-metadata-from-nested-render-array-when-returning-response
liquidcms avatar
lá cờ us
cảm ơn vì mẹo .. thật tốt khi biết. Mặc dù rất nhiều công việc chỉ đơn giản là sao chép một trường sang một trường mới dưới dạng ting 1 lần. Hiện tại, tôi chỉ cần đặt một var tĩnh trong tập lệnh cập nhật và sau đó sử dụng nó để bỏ qua các chức năng lưu/lưu trước của mình vì chúng không cần chạy khi bản cập nhật này đang được chạy.
4uk4 avatar
lá cờ cn
OK, nhưng điều này không giải quyết được vấn đề rò rỉ siêu dữ liệu vào bối cảnh kết xuất không xác định. Việc chạy render() hoặc mã chứa render() sẽ chỉ tạo ra siêu dữ liệu nổi nếu bạn có thể đảm bảo ngữ cảnh kết xuất thuộc về nội dung được kết xuất. Hầu hết đây là bối cảnh kết xuất trang khi tạo chủ đề cho các thành phần trang.

Đăng câu trả lời

Hầu hết mọi người không hiểu rằng việc đặt nhiều câu hỏi sẽ mở ra cơ hội học hỏi và cải thiện mối quan hệ giữa các cá nhân. Ví dụ, trong các nghiên cứu của Alison, mặc dù mọi người có thể nhớ chính xác có bao nhiêu câu hỏi đã được đặt ra trong các cuộc trò chuyện của họ, nhưng họ không trực giác nhận ra mối liên hệ giữa câu hỏi và sự yêu thích. Qua bốn nghiên cứu, trong đó những người tham gia tự tham gia vào các cuộc trò chuyện hoặc đọc bản ghi lại các cuộc trò chuyện của người khác, mọi người có xu hướng không nhận ra rằng việc đặt câu hỏi sẽ ảnh hưởng—hoặc đã ảnh hưởng—mức độ thân thiện giữa những người đối thoại.