5

I have a paragraph type that contains a text field and a text format field. I also have a content type that takes an unlimited number of paragraphs of this type.

The paragraph type is called 'questions_and_answers' and the two fields are 'field_question' and 'field_answer'. I'd like to be able to programmatically append 'questions_and_answers' paragraphs to a content type.

In the example below I'm grabbing the content from a 'double' field and importing them into the paragraph reference field. Here's my code so far.

    $nids = \Drupal::entityQuery('node')
        ->condition('type', 'faq')
        ->execute();
    foreach ($nids as $nid) {
        $node      = \Drupal\node\Entity\NODE::load($nid);
        $questions = $node->field_questions_and_answers->getValue();
        foreach ($questions as $question) {
            $q         = $question['first'];
            $a         = $question['second'];
            $paragraph = Paragraph::create([
                    'title'          => $q,
                    'type'           => 'questions_and_answers',
                    'field_question' => $q,
                    'field_answer'   => $a,
                ]);
            $paragraph->save();
            $node->field_qs_and_as[] = $paragraph->id();
        }
        $node->save();
    }

However when I perform this action the node gets a number of question paragraphs added but they're completely empty and they can't even be deleted. What am I missing? How do you append multiple paragraphs you created to an entity reference field on a node?

3 Answers 3

14

When you add a paragraph you also need to pass the revision id:

  $node->field_qs_and_as[] = [
    'target_id' => $paragraph->id(),
    'target_revision_id' => $paragraph->getRevisionId(),
  ];
2
  • Yes, I assume field_qs_and_as is an entity_reference_revisions field because paragraphs doesn't support core entity_reference fields.
    – Berdir
    May 18, 2017 at 19:03
  • Hi, I have added like this, I can see all paragraphs on node view but when I edit node I can edit only last paragraph. Do you know why?
    – tasqyn
    Sep 6, 2019 at 4:57
4

I've found it preferable to pass the entity object instead of manually setting the IDs yourself:

$node->field_qs_and_as[] = $paragraph;
$node->save();

Only make one call to $node->save() of course, after you've added/edited all the paragraph entities you want.

The primary reason for this is that when I set the reference array values instead, at least in the case of a newly created paragraph, the paragraph does not end up with a parent entity set. If you later need to call $paragraph->getParentEntity() or otherwise make use of Paragraphs' ability to trace the relationship in the reverse direction, that will be a problem.

I haven't looked at the code paths but it makes sense that if you call ->save() on the Paragraph it will not be able to detect a parent on its own. I would imagine the Entity Reference Revisions code handling array values then assumes that the relationship must already established on the child entity, if it's being passed existing IDs instead of an object.

0

I spent hours make it work, the problem was when adding a paragraph to my multivalues node field, the existing values were lost. I finally came to this working solution (retrieving existing paragraphs and adding them back together with the new paragraph), but I feel I'm missing something...

$currentUser = \Drupal\user\Entity\User::load(\Drupal::currentUser()->id());
$product = Node::load($form_state->getValue('product_id'));

//create new ordered_item paragraph
$order = Paragraph::create(['type' =>'item_ordered']);
$order->field_item_ordered_number = $form_state->getValue('quantity');
$order->field_item_ordered_product = $product->id();
$order->uid = $currentUser->id();
$order->save();

$order_items[] = [
'target_id' => $order->id(),
'target_revision_id' => $order->getRevisionId(),
];

//check if user has already a cart
$cart=\Drupal::service('dpnews_home.get_user_infos')->getUserCart($currentUser);

foreach ($cart->field_ordered_item as $item) {
  $existing_order=$item->entity;
  $order_items[] = [
  'target_id' => $existing_order->id(),
  'target_revision_id' => $existing_order->getRevisionId(),
  ];
}
//if not create new cart for user
if(!isset($cart)){
  $cart = Node::create(['type' => 'panier']);
  $cart->uid = $currentUser->id();
  $cart->title= 'Panier en cours - utilisateur '.$currentUser->id();
  $cart->save();
}

//add ordered item to cart
$cart->set('field_ordered_item',$order_items);
$cart->save();

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.