Entity metadata wrappers

Last updated on
4 March 2024

Drupal 7 will no longer be supported after January 5, 2025. Learn more and find resources for Drupal 7 sites

This documentation needs work. See "Help improve this page" in the sidebar.

Table of contents

Introduction

The contributed Entity API module provides wrapper classes that make dealing with the values of an entity's properties and fields easier.

Wrappers make it easier to get and set the values of fields and properties as well as to programmatically retrieve additional information about these elements and iterate over lists of values in a consistent manner.

For example consider the following method of accessing the value of a field attached to a node. This is a pattern that we see used often when working with entities in Drupal. However there are a couple of things that make this less than ideal. For example what if the user had requested the page in a different language? Or what about the case where the ['value'] key just doesn't exist like with image and file fields?

$node->field_custom_field_number[LANGUAGE_NONE][0]['value'];

Using metadata wrappers from the entity module we can access this information like so:

$node_wrapper = entity_metadata_wrapper('node', $node);
$node_wrapper->field_custom_field_number->value(); 

How about an example of making things consistent? All Drupal entities have a label of some sort. A string that can be treated as the canonical human readable name of an entity. All nodes have a title property and all user accounts have a name property. Given a standard Drupal entity it can be hard to know which property should be treated as the label. Metadata wrappers provide us with a consistent way of getting at this kind of information for any entity.

// Unified way of getting $node->title, $user->name, ...
$wrapper->label();

// Unified way of getting $node->nid, $user->uid, ...
$wrapper->getIdentifier();

// Unified way of getting $node->type, ...
$wrapper->getBundle();

Examples

For making use of this information (metadata) the module provides some wrapper classes which ease getting and setting values.

For wrapping an entity object you can use the procedural function (as below):

$wrapper = entity_metadata_wrapper('node', $node);

Or since Entity API 7.x-1.6, you can also use Entity::wrapper():

$wrapper = $entity->wrapper();

This only works however if the $entity object uses the Entity class provided by the Entity API module.

Also if you know type and ID of your entity, you can wrap it straight away:

$wrapper = entity_metadata_wrapper('node', $nid);

The wrapper supports chained usage for retrieving wrappers of entity properties, e.g. To get a
node author's mail address one could use:

  $wrapper->author->mail->value();

To update the user's mail address one could use

$wrapper->author->mail->set('sepp@example.com');

or

$wrapper->author->mail = 'sepp@example.com';

The wrappers always return the data as described in the property
information, which may be retrieved directly via entity_get_property_info()
or from the wrapper:

$mail_info = $wrapper->author->mail->info();

In order to force getting a textual value sanitized for output one can use,
e.g.

$wrapper->title->value(array('sanitize' => TRUE));

to get the sanitized node title. When a property is already returned
sanitized by default, like the node body, one possibly wants to get the
not-sanitized data as it would appear in a browser for other use-cases.
To do so one can enable the 'decode' option, which ensures for any sanitized
data the tags are stripped and HTML entities are decoded before the property
is returned:

$wrapper->body->value->value(array('decode' => TRUE));

That way one always gets the data as shown to the user. However if you
really want to get the raw, unprocessed value, even for sanitized textual
data, you can do so via:

$wrapper->body->raw();

Many more examples can be found in the tests of the entity module.

Example of using value(), set() and save()

<?php
$node_wrapper = entity_metadata_wrapper('node', $node);
$var = $node_wrapper->field_number->value() + 1;
$node_wrapper->field_number->set($var);
$node_wrapper->save();
?>

If you need to save a file into a field you must pass the file object or an array with a ``fid`` key:

<?php

  $w_containing_node = entity_metadata_wrapper('node', $nid);

  // Load the file object in any way
  $file_obj = file_load($fid);
  $w_containing_node->field_attachment_content->file->set( $file_obj );
  // ..or pass an array with the fid
  $w_containing_node->field_attachment_content->set( array('fid' => $fid) );
  $w_containing_node->save();

  // If an image field supports title or alt, you can set them in 2 ways.
  // Set both file and title with an array.
  $w_containing_node->field_image->set(array('fid' => $fid, 'title' => $title));
  // Set both file and title separately.
  $image_obj = file_load($fid);
  $w_containing_node->field_image->file = $image_obj;
  $w_containing_node->field_image->title = $title;
  $w_containing_node->save();
?>

Example of creating a node

You need to set the content type and user ID on a new node entity; and then that can be immediately passed in to entity_metadata_wrapper.

// Create an Entity.
$node = entity_create('node', array('type' => 'image'));
// Specify the author.
$node->uid = $user->uid;
// Create a Entity Wrapper of that new Entity.
$emw_node = entity_metadata_wrapper('node', $node);
// Set a title and some text field value.
$emw_node->title = 'Test node';
$emw_node->field_text_field->set('Field value text');
// And save it.
$emw_node->save();

Example using field collections

<?php
    // Populate the fields.
    $ewrapper = entity_metadata_wrapper('node', $node);
    $ewrapper->field_lead_contact_name->set($contact_name);
    $ewrapper->field_lead_contact_phone->set($contact_phone);
    $ewrapper->field_lead_contact_email->set($contact_email);  
 
    // Create the collection entity and set it's "host".
    $collection = entity_create('field_collection_item', array('field_name' => 'field_facilities_requested'));
    $collection->setHostEntity('node', $node);  

    // Now define the collection parameters.
    $cwrapper = entity_metadata_wrapper('field_collection_item', $collection);
    $cwrapper->field_facility->set(intval($offset));
    $cwrapper->save();  

    // Save.
    $ewrapper->save();
?>

Example grabbing standard entity object

In some cases it is necessary to get a copy of the entity in the stdClass form so that module functions can use it. Most drupal modules expect you to NOT pass in an EntityDrupalWrapper object. In these cases you can do something like the following:

<?php

$wrapper = entity_metadata_wrapper('commerce_order', $order);
$wrapper->field_ship_to_address = "123 Some Rd. Someplace, CA, 99000"
$wrapper->save();

// We will use $wrapper->value() to get the stdClass version of the order.
commerce_order_status_update($wrapper->value(), 'checkout_complete', FALSE, NULL, t('Customer is on the checkout Review page'));
?>

Working with lists

A list value that contains wrappers, such as a multi-valued reference field, can be iterated over thus:

  $wrapper = entity_metadata_wrapper('node', $node);
  foreach ($wrapper->field_taxonomy_terms->getIterator() as $delta => $term_wrapper) {
    // $term_wrapper may now be accessed as a taxonomy term wrapper.
    $label = $term_wrapper->name->value();
  }

Setting values or adding values to a list value, such as a multi-valued entity reference field, can be accomplished in several ways.

You can set an array as the whole value:

  $containing_node = node_load($nid);
  $w_containing_node = entity_metadata_wrapper('node', $containing_node);

  $nids_to_set = array(42, 23);
  $w_containing_node->field_entity_reference_field->set($nids_to_set);

The field wrapper can be appended to using square bracket syntax, the same as when working with a normal array:

<?php
  // Setting or adding to a list using square bracket syntax
  $containing_node = node_load($nid);
  $w_containing_node = entity_metadata_wrapper('node', $containing_node);

  // This appends to what is already there, just like a normal array.
  $w_containing_node->field_entity_reference_field[] = 42;
  $w_containing_node->field_entity_reference_field[] = 23;
?>

Finally, you can get the array out of the field, manipulate it, and set it back:

<?php
  // Add to a list using the whole array.
  $containing_node = node_load($nid);
  $w_containing_node = entity_metadata_wrapper('node', $containing_node);

  $curr_list = $w_containing_node->field_entity_reference_field->value();
  if (!$curr_list)
    $curr_list = array();
  $curr_list[] = $new_nid;
  $w_containing_node->field_entity_reference_field->set($curr_list);
  $w_containing_node->save();

?>

Deleting values

To delete values, there is no ->delete() method on the fields. You have to use this way to correctly delete a value:

// Using an empty ->set(NULL) removes the value - without NULL you'll get a PHP notice that set($value) requires 1 parameter.
$wrapper->field_data->set(NULL);

// And handles correctly the deltas when using multiple values fields
$wrapper->field_data->offsetUnset($delta);

Get first value of multifield (multiple-value field)

Just set value index directly after field name:

$first_name = $wrapper->field_tags[0]->name->value();

Handling Exceptions

It's recommended to wrap code in try...catch section when you work with entity_metadata_wrapper() to catch EntityMetadataWrapperException.
You can add hints for you in watchdog for debugging errors. For example function name or line number. Example:

try {
  $node_wrapper = entity_metadata_wrapper('node', $node);
  $price = $node_wrapper->field_product->field_price->value();
} 
catch (EntityMetadataWrapperException $exc) {
  watchdog(
    'MODULE_NAME',
    'EntityMetadataWrapper exception in %function() <pre>@trace</pre>',
    array('%function' => __FUNCTION__, '@trace' => $exc->getTraceAsString()),
    WATCHDOG_ERROR
  );
}

Get Start-date and End-date values from Date fields

If you have Date fields (provided by Date module) you can get Start/End values from a field in this way:

$wrap_node = entity_metadata_wrapper('node', $node);
$start_date = $wrap_node->field_my_data->value()['value'];
$end_date = $wrap_node->field_my_data->value()['value2'];

or alternatively:

$wrap_node = entity_metadata_wrapper('node', $node);
$start_date = $wrap_node->field_my_data->value->value();
$end_date = $wrap_node->field_my_data->value2->value();

Getting information about properties and fields

getPropertyInfo() returns information about available properties and fields, but depend on the $info parameter passed to the entity_metadata_wrapper().

// Wrapper for entity type 'node', but not specific bundle.
$wrapper = entity_metadata_wrapper('node');
// Info will contain information only about properties and not about fields.
$info = $wrapper->getPropertyInfo();

And now, when bundle provided:

// Wrapper for entity type 'node' with specific bundle 'page' specified.
$wrapper = entity_metadata_wrapper('node', NULL, array('bundle' => 'page'));
// Info will contain information about both properties and fields.
$info = $wrapper->getPropertyInfo();

Getting Entity Translation based translations

For nodes with Entity Translation based translations, language() returns a node wrapper translated for specified language.

$langcode = 'ja';

$wrapper = entity_metadata_wrapper('node', $nid);
$wrapper->title->value();  // => source node title

$wrapper_translated = $wrapper->language($langcode);
$wrapper_translated->title->value();  // => translated node title

On the other hand, if you want to specify the language of the source node, you need to pass 3rd parameter to entity_metadata_wrapper().

$langcode = 'it';
$info = array('langcode' => $langcode);
$w = entity_metadata_wrapper('node', $nid, $info);

Rendering Fields from a Wrapper

$node = node_load(43);
$node_wrapper = entity_metadata_wrapper('node', $node, array(
    'langcode' => $GLOBALS['language'],
    'bundle' => 'subject'
));

$field_value = $node_wrapper->field_teaser_image->value();
$build = array(
    '#theme' => 'image',
    '#path' => $field_value['uri'],
    '#alt' => $field_value['alt'],
    '#title' => $field_value['title'],
    '#width' => $field_value['width'],
    '#height' => $field_value['height'],
);

print drupal_render($build);

Debugging or introspecting wrappers

To get a list of all available properties of a(n) (entity)wrapper, you can use the following snippet (requires the devel module to be installed and enabled):

dpm($wrapper->getPropertyInfo()); 

But this doesn't give you any of the property values.
To be able to see the values you can write your own helper to debug wrapped objects:

<?php
function _wrapper_debug($w) {
  $values = array();
  foreach ($w->getPropertyInfo() as $key => $val) {
    $values[$key] = $w->$key->value();
  }
  return $values;
}
?>

And then use it in your code:

<?php dpm(_wrapper_debug($some_wrapped_object)); ?>

Resources

Help improve this page

Page status: Needs work

You can: