22

I am iterating through a field collection, and wrapping the field collection items with an entity_metadata_wrapper. I would like to check for the existence of field before calling its value method (which results in an error on fields that do not have a value), but I cannot find a way to do so.

$field_collection_item = field_collection_item_load($id);
$item_wrapper = entity_metadata_wrapper('field_collection_item', $field_collection_item);

// this results in an error if the field_contrib_headshot field is empty
$headshot = $item_wrapper->field_contributor->field_contrib_headshot->value();

My current workaround is to use field_get_items to see if the field is empty, but i'd love to be able to do this through the metadata wrapper if possible.

8 Answers 8

27

Simply call the PHP function isset():

$headshot = array();
if (isset($item_wrapper->field_contributor->field_contrib_headshot)) {
  $headshot = $item_wrapper->field_contributor->field_contrib_headshot->value();
}

EntityStructureWrapper implements the __isset() function according the principe of Overloading.

1
  • Yes, this is always how I've done it, less tied into the internals and easier to read IMO. Upvoted!
    – star-szr
    May 16, 2014 at 22:12
9

Any time there is an entity reference or field collection, isset() has never worked for me. What does seem to work any time we have an entity reference is doing:

if($wrapped_entity->entity_reference_field->getIdentifier()) {
  // This code only fires if there is an entity reference or field collection set.
}
1
4

It looks like you have an entity_reference somewhere in there due to the method chaining. But, look at the __isset() method for EntityStructureWrapper.

Check like:

$has_headshot = $item_wrapper->field_contributor->__isset('field_contrib_headshot');

and then use an IF block to do your logic ...

EDIT:

$has_headshot is now valid check desired.

6
  • I'm not sure what you mean by "it looks like you have an entity reference somewhere", if you could explain that a little more i'd appreciate it. __isset works great on the field collection, although I need to add the full field name: field_contrib_headshot instead of contrib_headshot Nov 19, 2013 at 19:08
  • fields are values; a string, a number, whatever. field_contributor is referencing another field field_contrib_headshot ... you have nesting in there somehow. I'm assuming you're using entity_reference or something else like field_group to nest these things ... thats all I meant.
    – tenken
    Nov 19, 2013 at 19:14
  • what was the __isset() piece of code that worked for you ?
    – tenken
    Nov 19, 2013 at 19:18
  • It was: $item_wrapper->field_contributor->__isset('field_contrib_headshot') Nov 19, 2013 at 19:22
  • It feels weird to me to call the __isset() directly, why not: $has_headshot = isset($item_wrapper->field_contributor->field_contrib_headshot);
    – star-szr
    May 16, 2014 at 22:09
1
$wrapper = entity_metadata_wrapper('node', 123);
if($wrapper->__isset('field_middle_name')) {
    // Do something awesome with the middle name.
} else {
    // Don't do anything awesome, they don't have a middle name.
}

Entity reference fields and field collections

// also check if there is an identifier, __isset alone is not enough!
if ($wrapper->__isset('field_project_number') && $wrapper->field_project_number->getIdentifier()) {
    $number =  $wrapper->field_project_number->field_project_number_complete->value();
    return $number;
}

Copied and pasted straight from http://dropbucket.org/node/1201 but seems to be a better example than any other answer so far...

1

For EntityMetadataWrapper:

If you've got blocks of code running that shouldn't or if you've come across PHP errors look at some of the examples below. This example uses the property nid.

MAY ALL ERROR

if ($wrapper->__isset('nid')) {
  $var = $wrapper->nid->value();
}
else {
  // Do something it's FALSE;
}

OR

if ($wrapper->__isset('nid')) {
  $var = $wrapper->nid->getIdentifier();
}
else {
  // Do something it's FALSE;
}

OR

if ($wrapper->nid->value()) {
  // Do something it's TRUE.
}
else {
  // Do something it's FALSE;
}

You may find that using isset like so might evaluate to true even if the nid is not present. The ->getIdentifier(), or ->value(), or ->raw() may throw exceptions.

LIKELY ALWAYS TRUE

if (isset($wrapper->nid)) {
  // Do something it must be TRUE....Ah Hem wait.. this runs every time.
}

USE THIS INSTEAD

try {
  $var = $wrapper->nid->raw();
} 
catch (EntityMetadataWrapperException $e) {
  $var = FALSE;
}
0

I've found that isset() cannot be used on the result of a function call. Since a Boolean is returned with the following statement, I was able to verify that the wrapped element, in fact, had a value.

if ( $wrapper->field_media_alternate[0]->value() ) {
  //...valid logic...
} else {
  //...not valid logic...
}
0

People often get this wrong. When you call isset on an entity metadata wrapper, you're checking whether the entity bundle supports that property. It has nothing whatsoever to do with the actual value of the field.

There isn't really an independent method for checking whether a value is set. You just have to evaluate value() or, preferably, raw(). (You can also call count() if it's a multi-value field, but raw() will return an empty array so it's not actually required.)

$w = entity_metadata_wrapper('node', $nid);
//Start by checking whether the node bundle supports field_entityref_myfield.
if (isset($w->field_entityref_myfield)) {
  //If we called value(), then that would cause the referenced entity
  //to be loaded, whereas raw() just gives us the entity_id if the value
  //is set, and Null if it isn't.
  if ($w->field_entityref_myfield->raw()) {
    //Do some things based on the entity-reference being set.
  } else {
    //Do some other things based on the entity-reference NOT being set.
  }
}

To reiterate, raw() is the value you should use to check whether a field exists. It's reliable and computationally cheap.

0

Here is my personal helper function to get a value from a potentialy not set chain of entity references:

function _get_wrapped_value_ifset($wentity, $field_chain){
  $root = $wentity;
  try{
    foreach ( $field_chain as $field_name ) {
      $root = $root->{$field_name};
    }
    return $root->value();
  }
  catch (EntityMetadataWrapperException $e){
    return null;
  }
}

$wentity is the wrapped entity , $field_chain is an array of field_names like so:

[
  'field_reference_from_the_wentity',
  'field_wanted_field_from_the_referenced_entity'
] 

you may also do:

[
  'field_reference_from_the_wentity', 
  'field_reference_from_the_referenced_entity',
  ... 
  'field_wanted_field_from_the_N_referenced_entity'
]

it'll work !

Your Answer

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

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