Score:0

Empty node references on node creation and on node load

iq flag

I never noticed it, but:

  • If I create a node containing a reference and set the reference field to null, the field is still set as an EntityReferenceFieldItemList, e.g. the following code
echo "Creating a node with ref_field=null", PHP_EOL ;
$node = Node::create([
    'type' => 'my_type',
    'uid' => \Drupal::currentUser()->id(),
    'title' => "title",
    'field_ref_field' => null,
]) ;
// $node->field_ref_field = null ;
$node->save() ;

echo "Ref field is a " . gettype($node->field_ref_field) . ", and more specifically: " . get_class($node->field_ref_field), PHP_EOL ;
echo "Its id is ", $node->id(), PHP_EOL ;

produces on output

Creating a node with ref_field=null
Ref field is a object, and more specifically: Drupal\Core\Field\EntityReferenceFieldItemList
Its id is 933461

The same result occurs if I set ref_field to null after node creation, uncommenting the line that follows.

  • If I reload the field,
$node = Node::load(933461) ;
echo "Ref field is a " . gettype($evento->field_seduta), PHP_EOL ;

the result is

Field seduta is a NULL

As a consequence of this behaviour, to check if a reference field is valid I have either to check both the field itself and its target_id for nullness,

if (! $node->field_ref_field || ! $node->field_ref_field->target_id)

that is annoying, or to make sure that a certain code fragment is reached after node creation or node loading, that is fragile.

Am I missing something? What is the reason of this strange behaviour?

unusedspoon avatar
aq flag
You'd have to do this anyway, even if you added a node as a reference then you later removed that reference the field would still exist. Drupal's not going to delete all the field tables/stored defininition and re-create them every time
Francesco Marchetti-Stasi avatar
iq flag
@unusedspoon, I'm not sure I understand your point, I never mentione the definition of the field, only its value for a specific node. Also, I was wondering why the behaviour on creation is different from that on loading.
Score:2
de flag

The value of the field will be NULL, but the field itself is a FieldItem. That's how Drupal works, as the FieldItem class manages the values of the field, even when there are no values set.

The solution to your conditional is to check if the field is empty:

if (!empty($node->field_ref_field)) {
  // There are values.
}
else {
  // There are no values.
}
Francesco Marchetti-Stasi avatar
iq flag
Oh, right, thank you. I have not a large experience with PHP in general, so some of its usage patterns still escape me. If I interpret correctly the documentation, this works because `empty()` calls the `isset()` overloading method defined by `FieldItemList`, right?...
Jaypan avatar
de flag
I have no idea how empty() works under the hood, as it's core PHP. But `FIeldItemList` is Traversable, and therefore empty() can be called on it, determining if there are any values.
Francesco Marchetti-Stasi avatar
iq flag
Concerning the inner workings of `empty()`, I just found in the documentation that it calls `__isset()` (if there is one defined) when invoked on inaccessible object properties, and `FieldItemList` defines one, so maybe that is relevant to the solution – not sure about that.
I sit in a Tesla and translated this thread with Ai:

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.