Puncte:0

$node->save() eșuează când rulează în post_update

drapel us

Am o funcție simplă hook_post_update care eșuează cu următoarea eroare:

[notificare] A început actualizarea: ssc_custom_post_update_9001

[eroare] LogicException: contextul de randare este gol, deoarece render() a fost apelat în afara unui apel renderRoot() sau renderPlain(). Utilizare renderPlain()/renderRoot() sau #lazy_builder/#pre_render în schimb. în Drupal\Core\Render\Renderer->doRender() (linia 244 din E:\www\myssc\html\core\lib\Drupal\Core\Render\Renderer.php). [eroare] Contextul de randare este gol, deoarece render() a fost apelat în afara unui apel renderRoot() sau renderPlain(). Utilizare renderPlain()/renderRoot() sau #lazy_builder/#pre_render în schimb. [eroare] Actualizare eșuată: ssc_custom_post_update_9001

În linia 171 ProcessBase.php:

Nu se poate decoda ieșirea în JSON: eroare de sintaxă

[EROARE] [nod] [2022-03-12T04:58:35] LogicException: Redare context este gol, deoarece render() a fost apelat în afara unui renderRoot() sau apelul renderPlain(). Utilizați renderPlain()/renderRoot() sau #lazy_builder/#pre_re nder în schimb. în Drupal\Core\Render\Renderer->doRender() (linia 244 din E:\www\myssc\html\core\lib\Drupal\C ore\Render\Renderer.php). | uid: 0 | cerere-uri: http://default/ | referiți: | ip: 127.0.0.1 | legătură:
{ „0”: { „ssc_custom”: { „9001”: { „#abort”: { „succes”: fals, "query": "Drupal\Core\Entity\EntityStorageException: Ren der context este gol, deoarece render() a fost apelat în afara a Apelul renderRoot() sau renderPlain(). Utilizați re nderPlain()/renderRoot() sau #lazy_builder/#pre_render în schimb. în Drupal\Core\Ent
ity\Sql\SqlContentEntityStorage->save() (linia 810 din E:\www\myssc\html\core\lib\Drupal\Core\Entity\Sql\SqlContentEntityStorage.php)." } } }, „#abandona”: [ „ssc_custom_post_update_9001” ] }, „drush_batch_process_finished”: adevărat }

Am redus codul la minimum:

utilizați Drupal\Core\Entity\EntityStorageInterface;
utilizați Drupal\Core\Entity\EntityTypeManagerInterface;
utilizați Drupal\node\NodeInterface;

funcția ssc_custom_post_update_9001(&$sandbox) {
  /** @var \Drupal\node\NodeStorageInterface $node_storage */
  $node_storage = \Drupal::entityTypeManager()->getStorage('nod');

  // Câte entități trebuie procesate pe lot.
  $limita = 5;

  $node_ids = $node_storage->getQuery()
    ->accessCheck(FALSE)
    ->condition('tip', 'articol')
    ->interval(0, $limită)
    ->execute();
  // Încărcați entități.
  $noduri = $node_storage->loadMultiple($node_ids);

  /** @var \Drupal\node\NodeInterface $nod */
  foreach ($noduri ca $nod) {
    $nod->setNewRevision();
    $nod->salvare();
  }

  $sandbox['#finished'] = 1;

}

Dacă rulez același cod direct (nu de la drush updb) merge bine. Rularea din meniul de administrare „Run updates”; de asemenea, nu reușește (deci nu este o problemă de drush).

Comentând $node->save() și eroarea nu apare.

sonfd avatar
drapel in
Se întâmplă acest lucru dacă încărcați și salvați un alt tip de conținut?
leymannx avatar
drapel ne
Nu așa funcționează lotul. Actualizările de conținut ar trebui să aibă loc în `hook_deploy_N` care rulează după importul configurației când se execută `drush deploy`.
4uk4 avatar
drapel cn
Dacă apare o eroare într-o funcție Drupal folosită în multe locuri diferite, trebuie să verificați stiva de apeluri de unde este apelată. Acest lucru ar putea indica un modul care se conectează la procesul de salvare a nodului.
liquidcms avatar
drapel us
Hmm, în mod ciudat, nu mai primesc notificări de la Drupal Answers.. @sonfd, da, orice tip de conținut.leymannx, care nu este sigur ce este hook_deploy, va arunca o privire; dar hook_post_update afirmă că este special pentru sarcini de genul acesta atunci când trebuie să actualizați conținutul site-ului, iar exemplele chiar se afișează folosind salvarea în lot și a nodurilor: https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Extension %21module.api.php/function/hook_post_update_NAME/9.0.x
liquidcms avatar
drapel us
@4uk4, da, acesta a fost următorul meu plan.. depanați în nucleu pentru a vedea unde eșuează și pentru a vedea dacă pot spune ce modul provoacă acest lucru. Am eliminat tot codul meu personalizat (care avea salvarea nodurilor) și nu a fost problema. Ciudat că nu există o modalitate de a rula o actualizare care să poată ocoli această problemă, deoarece pare o prostie să fi remediat o duzină (da, probabil nu atât de multe) module de contribuție pentru a face o simplă actualizare de conținut. Alternativ, pot oferi clienților mei un buton de apăsat după ce site-ul este actualizat; dar cu siguranță o regresie de la D7 că nu pot avea scriptul meu de implementare să facă actualizarea.
liquidcms avatar
drapel us
@leymannz, nu există așa ceva ca hook_deploy - posibil ceva adăugat de un modul contrib? Desfășurați poate?
drapel cn
Este un cârlig @liquidcms
Puncte:2
drapel cn

Puteți reproduce eroarea cu Drush:

# drush php

>>> $build = ['#markup' => 'TEST'];
=> [
     "#markup" => "TEST",
   ]

>>> $rendered = \Drupal::service('renderer')->render($build);
LogicException cu mesajul „Contextul de redare este gol, deoarece render() a fost apelat în afara unui apel renderRoot() sau renderPlain(). Folosiți în schimb renderPlain()/renderRoot() sau #lazy_builder/#pre_render.'

>>> $rendered = \Drupal::service('renderer')->renderPlain($build);
=> Drupal\Core\Render\Markup {#4668
     marcaj: „TEST”,
   }

Deci, după cum spune mesajul de eroare, modulele care se cuplează în procesul de salvare a nodului ar trebui să utilizeze renderPlain() în schimb. Ei nu ar trebui să presupună că nodurile sunt întotdeauna salvate într-un context de randare al unei pagini Drupal tematice.

Exemplu de cod pentru redarea unei vizualizări izolat:

$build = $view->buildRenderable();
$rendered = \Drupal::service('renderer')->renderPlain($build);
liquidcms avatar
drapel us
Se pare că problema este codul meu personalizat. Am un cod care rulează pe salvarea/presavarea nodului care încearcă să obțină valori dintr-o vizualizare și folosește advancedRender() care presupun că cauzează această problemă. Dezamăgitor că codul meu funcționează așa cum ar trebui atunci când nodurile sunt în mod normal salvate, dar în post_update sunt blocat să fac acest lucru. Destul de ușor de rezolvat, deoarece aceste funcții nu trebuie să fie rulate în timpul acestei actualizări - dar ciudat ar trebui să fac acest hack.
4uk4 avatar
drapel cn
Dacă funcția render() nu este în controlul dvs., ca aici într-o vizualizare, puteți include codul în propriul dvs. RenderContext și renunțați la metadatele bulgate. Drupal face acest lucru, de exemplu, atunci când redă e-mailuri. Vedeți https://drupal.stackexchange.com/questions/245715/how-to-get-cache-metadata-from-nested-render-array-when-returning-response
liquidcms avatar
drapel us
multumesc pentru pont.. e bine de stiut. Deși multă muncă pentru a copia pur și simplu un câmp într-un câmp nou ca o singură dată. Deocamdată am setat pur și simplu o var static în scriptul de actualizare și apoi o folosesc pentru a ignora funcțiile mele de salvare/presalvare, deoarece nu trebuie să fie executate atunci când se execută această actualizare.
4uk4 avatar
drapel cn
OK, dar acest lucru nu rezolvă problema cu scurgerea metadatelor într-un context de randare necunoscut. Rularea render() sau codul care conține render() ar trebui să afișeze metadate numai dacă vă puteți asigura că contextul de randare aparține conținutului redat. De cele mai multe ori acesta este contextul de randare a paginii atunci când temați elementele paginii.

Postează un răspuns

Majoritatea oamenilor nu înțeleg că a pune multe întrebări deblochează învățarea și îmbunătățește legătura interpersonală. În studiile lui Alison, de exemplu, deși oamenii își puteau aminti cu exactitate câte întrebări au fost puse în conversațiile lor, ei nu au intuit legătura dintre întrebări și apreciere. În patru studii, în care participanții au fost implicați în conversații ei înșiși sau au citit transcrieri ale conversațiilor altora, oamenii au avut tendința să nu realizeze că întrebarea ar influența – sau ar fi influențat – nivelul de prietenie dintre conversatori.