0

[Note, this question is almost identical to this one for Drupal 7, but since I never used it I cannot understand how the proposed solution can be ported to Drupal 8]

I have a parent node type, let's call it Parent, which holds a list of references to a child type, let's call it Child. A child also has a reference to its parent node. For business reasons beyond the parent-child model, a parent has to be created from the edit form of the child; from the edit form of the parent I can link more children.

So I set up a link from the edit form of the child which points to a Controller with a code like the following:

$parent = Node::create([
  'type' => 'parent_nodetype',
  'langcode' => 'en',
  'created' => REQUEST_TIME,
  'changed' => REQUEST_TIME,
  'uid' => $this->currentUser()->id(),
  'title' => 'Parent of ' . $child->get('title')->getString(),
  'field_children' => [$child_id],
]) ;
$parent->save() ;
// ...maybe more code here...
return $this->redirect('entity.node.edit_form', ['node' => $parent->id()]) ;

If I do just this, the parent node is created and I am redirected to its edit form. But I also want to insert the reference of the child to the parent, so at the location of the comment in the above code I add

$parent_id = $parent->id() ;
$child->set('field_parent', $parent_id) ;
$child->save() ;

In this second situation, the redirect is not executed, so I remain in edit form of the child. I tried to save the parent again after

Searching for similar problems, I got the idea of moving the association from child to parent in a hook, so I wrote something like the following:

function mymodule_node_insert(Drupal\Core\Entity\EntityInterface $node) {
  if ($node->getType() === 'parent_nodetype') {
    foreach ($node->get('field_children') as $item) {
      $child_id = $item->getValue()['target_id'] ;
      $child = Node::load($child_id) ;
      $child->set('field_parent', $node->id()) ;
      $child->save() ;
    }
  }
}

but even in this case the redirection does not take place; it is as if the $child->save() statement prevents the redirection, wherever it is called.

Is it really so? How can I achieve the desired result?

EDIT: I tried to have a $parent->save() as a final instruction, which is not difficult:

$parent = Node::create([
//    ... same code as before, only the last line is commented 
//    so the next save is guaranteed to be executed ...
//      'field_children' => [$child_id],
]) ;
$parent->save() ;

$parent_id = $parent->id() ;
$child->set('field_parent', $parent_id) ;
$child->save() ;

$parent = Node::load($parent_id) ;
$parent->set('field_children', [ $child_id ] ) ;
$parent->save() ;
return $this->redirect('entity.node.edit_form', ['node' => $parent->id()]) ;

but redirection still doesn't work, so my guess that it was the save on the child to prevent redirection is false: maybe any operation on other entities prevents it...

  • 1
    Shouldn't this go as a custom submit handler in the form? You should not do redirects from hook_entity_insert (or presave or update). – Kevin Dec 3 '18 at 17:14
  • Oh, right, I see your point: I was trying to treat my "creation link" as an action separated from the form it lives on. Still, the redirection works as long as I don't alter the child entity: if I do, I am forced to remain in its edit form. Anyway you are right, leaving a form without checking for its state sounds like a bad idea... I'll first try to transform the link to an action tab and see where that leads me, maybe it's easier than a custom submit handler. Thanks for the comment! – Francesco Marchetti-Stasi Dec 3 '18 at 17:36
  • I exposed the link as an action tab, and that solved my problem. Many thanks to @Kevin for pointing out the drawbacks of the solution I was trying to implement. – Francesco Marchetti-Stasi Dec 6 '18 at 10:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.